Port to the use of GFile instead of URIs and merge gio document loader and saver

into document loader and saver
This commit is contained in:
JosephMcc 2017-01-14 11:48:19 -08:00
parent 6a997b1b79
commit f21c6e9361
39 changed files with 3420 additions and 4078 deletions

View File

@ -535,6 +535,7 @@ init_bookmarks (XedFileBookmarksStore * model)
{ {
if (**line) if (**line)
{ {
GFile *location;
gchar *pos; gchar *pos;
gchar *name; gchar *name;
@ -553,10 +554,12 @@ init_bookmarks (XedFileBookmarksStore * model)
/* the bookmarks file should contain valid /* the bookmarks file should contain valid
* URIs, but paranoia is good */ * URIs, but paranoia is good */
if (xed_utils_is_valid_uri (*line)) location = g_file_new_for_uri (*line);
if (xed_utils_is_valid_location (location))
{ {
added |= add_bookmark (model, name, *line); added |= add_bookmark (model, name, *line);
} }
g_object_unref (location);
} }
} }
@ -844,14 +847,14 @@ xed_file_bookmarks_store_new (void)
return model; return model;
} }
gchar * GFile *
xed_file_bookmarks_store_get_uri (XedFileBookmarksStore *model, xed_file_bookmarks_store_get_location (XedFileBookmarksStore *model,
GtkTreeIter *iter) GtkTreeIter *iter)
{ {
GObject *obj; GObject *obj;
GFile *file = NULL; GFile *file = NULL;
guint flags; guint flags;
gchar * ret = NULL; GFile *ret = NULL;
gboolean isfs; gboolean isfs;
g_return_val_if_fail (XED_IS_FILE_BOOKMARKS_STORE (model), NULL); g_return_val_if_fail (XED_IS_FILE_BOOKMARKS_STORE (model), NULL);
@ -884,7 +887,7 @@ xed_file_bookmarks_store_get_uri (XedFileBookmarksStore *model,
if (file) if (file)
{ {
ret = g_file_get_uri (file); ret = g_file_dup (file);
g_object_unref (file); g_object_unref (file);
} }

View File

@ -80,7 +80,7 @@ GType xed_file_bookmarks_store_get_type (void) G_GNUC_CONST;
void _xed_file_bookmarks_store_register_type (GTypeModule *type_module); void _xed_file_bookmarks_store_register_type (GTypeModule *type_module);
XedFileBookmarksStore *xed_file_bookmarks_store_new (void); XedFileBookmarksStore *xed_file_bookmarks_store_new (void);
gchar *xed_file_bookmarks_store_get_uri (XedFileBookmarksStore * model, GFile *xed_file_bookmarks_store_get_location (XedFileBookmarksStore * model,
GtkTreeIter * iter); GtkTreeIter * iter);
void xed_file_bookmarks_store_refresh (XedFileBookmarksStore * model); void xed_file_bookmarks_store_refresh (XedFileBookmarksStore * model);

View File

@ -1,5 +1,5 @@
VOID:UINT,STRING VOID:UINT,STRING
VOID:STRING,STRING VOID:OBJECT,OBJECT
BOOL:OBJECT,POINTER BOOL:OBJECT,POINTER
BOOL:POINTER BOOL:POINTER
BOOL:VOID BOOL:VOID

View File

@ -178,13 +178,16 @@ message_get_root_cb (XedMessageBus *bus,
WindowData *data) WindowData *data)
{ {
XedFileBrowserStore *store; XedFileBrowserStore *store;
gchar *uri; GFile *location;
store = xed_file_browser_widget_get_browser_store (data->widget); store = xed_file_browser_widget_get_browser_store (data->widget);
uri = xed_file_browser_store_get_virtual_root (store); location = xed_file_browser_store_get_virtual_root (store);
xed_message_set (message, "uri", uri, NULL); if (location)
g_free (uri); {
xed_message_set (message, "location", location, NULL);
g_object_unref (location);
}
} }
static void static void
@ -192,10 +195,10 @@ message_set_root_cb (XedMessageBus *bus,
XedMessage *message, XedMessage *message,
WindowData *data) WindowData *data)
{ {
gchar *root = NULL; GFile *root;
gchar *virtual = NULL; GFile *virtual = NULL;
xed_message_get (message, "uri", &root, NULL); xed_message_get (message, "location", &root, NULL);
if (!root) if (!root)
return; return;
@ -207,9 +210,6 @@ message_set_root_cb (XedMessageBus *bus,
xed_file_browser_widget_set_root_and_virtual_root (data->widget, root, virtual); xed_file_browser_widget_set_root_and_virtual_root (data->widget, root, virtual);
else else
xed_file_browser_widget_set_root (data->widget, root, TRUE); xed_file_browser_widget_set_root (data->widget, root, TRUE);
g_free (root);
g_free (virtual);
} }
static void static void
@ -278,23 +278,30 @@ message_set_emblem_cb (XedMessageBus *bus,
static gchar * static gchar *
item_id (const gchar *path, item_id (const gchar *path,
const gchar *uri) GFile *location)
{ {
return g_strconcat (path, "::", uri, NULL); gchar *uri;
gchar *id;
uri = g_file_get_uri (location);
id = g_strconcat (path, "::", uri, NULL);
g_free (uri);
return id;
} }
static gchar * static gchar *
track_row (WindowData *data, track_row (WindowData *data,
XedFileBrowserStore *store, XedFileBrowserStore *store,
GtkTreePath *path, GtkTreePath *path,
const gchar *uri) GFile *location)
{ {
GtkTreeRowReference *ref; GtkTreeRowReference *ref;
gchar *id; gchar *id;
gchar *pathstr; gchar *pathstr;
pathstr = gtk_tree_path_to_string (path); pathstr = gtk_tree_path_to_string (path);
id = item_id (pathstr, uri); id = item_id (pathstr, location);
ref = gtk_tree_row_reference_new (GTK_TREE_MODEL (store), path); ref = gtk_tree_row_reference_new (GTK_TREE_MODEL (store), path);
g_hash_table_insert (data->row_tracking, g_strdup (id), ref); g_hash_table_insert (data->row_tracking, g_strdup (id), ref);
@ -311,28 +318,28 @@ set_item_message (WindowData *data,
XedMessage *message) XedMessage *message)
{ {
XedFileBrowserStore *store; XedFileBrowserStore *store;
gchar *uri = NULL; GFile *location;
guint flags = 0; guint flags = 0;
gchar *track_id; gchar *track_id;
store = xed_file_browser_widget_get_browser_store (data->widget); store = xed_file_browser_widget_get_browser_store (data->widget);
gtk_tree_model_get (GTK_TREE_MODEL (store), iter, gtk_tree_model_get (GTK_TREE_MODEL (store), iter,
XED_FILE_BROWSER_STORE_COLUMN_URI, &uri, XED_FILE_BROWSER_STORE_COLUMN_LOCATION, &location,
XED_FILE_BROWSER_STORE_COLUMN_FLAGS, &flags, XED_FILE_BROWSER_STORE_COLUMN_FLAGS, &flags,
-1); -1);
if (!uri) if (!location)
return; return;
if (path && gtk_tree_path_get_depth (path) != 0) if (path && gtk_tree_path_get_depth (path) != 0)
track_id = track_row (data, store, path, uri); track_id = track_row (data, store, path, location);
else else
track_id = NULL; track_id = NULL;
xed_message_set (message, xed_message_set (message,
"id", track_id, "id", track_id,
"uri", uri, "location", location,
NULL); NULL);
if (xed_message_has_key (message, "is_directory")) if (xed_message_has_key (message, "is_directory"))
@ -342,7 +349,6 @@ set_item_message (WindowData *data,
NULL); NULL);
} }
g_free (uri);
g_free (track_id); g_free (track_id);
} }
@ -353,19 +359,18 @@ custom_message_filter_func (XedFileBrowserWidget *widget,
FilterData *data) FilterData *data)
{ {
WindowData *wdata = get_window_data (data->window); WindowData *wdata = get_window_data (data->window);
gchar *uri = NULL; GFile *location;
guint flags = 0; guint flags = 0;
gboolean filter = FALSE; gboolean filter = FALSE;
GtkTreePath *path; GtkTreePath *path;
gtk_tree_model_get (GTK_TREE_MODEL (store), iter, gtk_tree_model_get (GTK_TREE_MODEL (store), iter,
XED_FILE_BROWSER_STORE_COLUMN_URI, &uri, XED_FILE_BROWSER_STORE_COLUMN_LOCATION, &location,
XED_FILE_BROWSER_STORE_COLUMN_FLAGS, &flags, XED_FILE_BROWSER_STORE_COLUMN_FLAGS, &flags,
-1); -1);
if (!uri || FILE_IS_DUMMY (flags)) if (!location || FILE_IS_DUMMY (flags))
{ {
g_free (uri);
return FALSE; return FALSE;
} }
@ -420,7 +425,7 @@ message_add_filter_cb (XedMessageBus *bus,
// Check if the message type has the correct arguments // Check if the message type has the correct arguments
if (xed_message_type_lookup (message_type, "id") != G_TYPE_STRING || if (xed_message_type_lookup (message_type, "id") != G_TYPE_STRING ||
xed_message_type_lookup (message_type, "uri") != G_TYPE_STRING || xed_message_type_lookup (message_type, "location") != G_TYPE_FILE ||
xed_message_type_lookup (message_type, "is_directory") != G_TYPE_BOOLEAN || xed_message_type_lookup (message_type, "is_directory") != G_TYPE_BOOLEAN ||
xed_message_type_lookup (message_type, "filter") != G_TYPE_BOOLEAN) xed_message_type_lookup (message_type, "filter") != G_TYPE_BOOLEAN)
{ {
@ -429,7 +434,7 @@ message_add_filter_cb (XedMessageBus *bus,
cbmessage = xed_message_type_instantiate (message_type, cbmessage = xed_message_type_instantiate (message_type,
"id", NULL, "id", NULL,
"uri", NULL, "location", NULL,
"is_directory", FALSE, "is_directory", FALSE,
"filter", FALSE, "filter", FALSE,
NULL); NULL);
@ -647,13 +652,13 @@ register_methods (XedWindow *window,
xed_message_bus_register (bus, xed_message_bus_register (bus,
MESSAGE_OBJECT_PATH, "get_root", MESSAGE_OBJECT_PATH, "get_root",
1, 1,
"uri", G_TYPE_STRING, "location", G_TYPE_FILE,
NULL); NULL);
xed_message_bus_register (bus, xed_message_bus_register (bus,
MESSAGE_OBJECT_PATH, "set_root", MESSAGE_OBJECT_PATH, "set_root",
1, 1,
"uri", G_TYPE_STRING, "location", G_TYPE_FILE,
"virtual", G_TYPE_STRING, "virtual", G_TYPE_STRING,
NULL); NULL);
@ -749,11 +754,9 @@ store_row_inserted (XedFileBrowserStore *store,
GtkTreeIter *iter, GtkTreeIter *iter,
MessageCacheData *data) MessageCacheData *data)
{ {
gchar *uri = NULL;
guint flags = 0; guint flags = 0;
gtk_tree_model_get (GTK_TREE_MODEL (store), iter, gtk_tree_model_get (GTK_TREE_MODEL (store), iter,
XED_FILE_BROWSER_STORE_COLUMN_URI, &uri,
XED_FILE_BROWSER_STORE_COLUMN_FLAGS, &flags, XED_FILE_BROWSER_STORE_COLUMN_FLAGS, &flags,
-1); -1);
@ -764,8 +767,6 @@ store_row_inserted (XedFileBrowserStore *store,
set_item_message (wdata, iter, path, data->message); set_item_message (wdata, iter, path, data->message);
xed_message_bus_send_message_sync (wdata->bus, data->message); xed_message_bus_send_message_sync (wdata->bus, data->message);
} }
g_free (uri);
} }
static void static void
@ -774,14 +775,12 @@ store_row_deleted (XedFileBrowserStore *store,
MessageCacheData *data) MessageCacheData *data)
{ {
GtkTreeIter iter; GtkTreeIter iter;
gchar *uri = NULL;
guint flags = 0; guint flags = 0;
if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (store), &iter, path)) if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (store), &iter, path))
return; return;
gtk_tree_model_get (GTK_TREE_MODEL (store), &iter, gtk_tree_model_get (GTK_TREE_MODEL (store), &iter,
XED_FILE_BROWSER_STORE_COLUMN_URI, &uri,
XED_FILE_BROWSER_STORE_COLUMN_FLAGS, &flags, XED_FILE_BROWSER_STORE_COLUMN_FLAGS, &flags,
-1); -1);
@ -792,8 +791,6 @@ store_row_deleted (XedFileBrowserStore *store,
set_item_message (wdata, &iter, path, data->message); set_item_message (wdata, &iter, path, data->message);
xed_message_bus_send_message_sync (wdata->bus, data->message); xed_message_bus_send_message_sync (wdata->bus, data->message);
} }
g_free (uri);
} }
static void static void
@ -802,20 +799,20 @@ store_virtual_root_changed (XedFileBrowserStore *store,
MessageCacheData *data) MessageCacheData *data)
{ {
WindowData *wdata = get_window_data (data->window); WindowData *wdata = get_window_data (data->window);
gchar *uri; GFile *vroot;
uri = xed_file_browser_store_get_virtual_root (store); vroot = xed_file_browser_store_get_virtual_root (store);
if (!uri) if (!vroot)
return; return;
xed_message_set (data->message, xed_message_set (data->message,
"uri", uri, "location", vroot,
NULL); NULL);
xed_message_bus_send_message_sync (wdata->bus, data->message); xed_message_bus_send_message_sync (wdata->bus, data->message);
g_free (uri); g_object_unref (vroot);
} }
static void static void
@ -870,28 +867,28 @@ register_signals (XedWindow *window,
MESSAGE_OBJECT_PATH, "root_changed", MESSAGE_OBJECT_PATH, "root_changed",
0, 0,
"id", G_TYPE_STRING, "id", G_TYPE_STRING,
"uri", G_TYPE_STRING, "location", G_TYPE_FILE,
NULL); NULL);
begin_loading_type = xed_message_bus_register (bus, begin_loading_type = xed_message_bus_register (bus,
MESSAGE_OBJECT_PATH, "begin_loading", MESSAGE_OBJECT_PATH, "begin_loading",
0, 0,
"id", G_TYPE_STRING, "id", G_TYPE_STRING,
"uri", G_TYPE_STRING, "location", G_TYPE_FILE,
NULL); NULL);
end_loading_type = xed_message_bus_register (bus, end_loading_type = xed_message_bus_register (bus,
MESSAGE_OBJECT_PATH, "end_loading", MESSAGE_OBJECT_PATH, "end_loading",
0, 0,
"id", G_TYPE_STRING, "id", G_TYPE_STRING,
"uri", G_TYPE_STRING, "location", G_TYPE_FILE,
NULL); NULL);
inserted_type = xed_message_bus_register (bus, inserted_type = xed_message_bus_register (bus,
MESSAGE_OBJECT_PATH, "inserted", MESSAGE_OBJECT_PATH, "inserted",
0, 0,
"id", G_TYPE_STRING, "id", G_TYPE_STRING,
"uri", G_TYPE_STRING, "location", G_TYPE_FILE,
"is_directory", G_TYPE_BOOLEAN, "is_directory", G_TYPE_BOOLEAN,
NULL); NULL);
@ -899,7 +896,7 @@ register_signals (XedWindow *window,
MESSAGE_OBJECT_PATH, "deleted", MESSAGE_OBJECT_PATH, "deleted",
0, 0,
"id", G_TYPE_STRING, "id", G_TYPE_STRING,
"uri", G_TYPE_STRING, "location", G_TYPE_FILE,
"is_directory", G_TYPE_BOOLEAN, "is_directory", G_TYPE_BOOLEAN,
NULL); NULL);
@ -907,7 +904,7 @@ register_signals (XedWindow *window,
message = xed_message_type_instantiate (inserted_type, message = xed_message_type_instantiate (inserted_type,
"id", NULL, "id", NULL,
"uri", NULL, "location", NULL,
"is_directory", FALSE, "is_directory", FALSE,
NULL); NULL);
@ -923,7 +920,7 @@ register_signals (XedWindow *window,
message = xed_message_type_instantiate (deleted_type, message = xed_message_type_instantiate (deleted_type,
"id", NULL, "id", NULL,
"uri", NULL, "location", NULL,
"is_directory", FALSE, "is_directory", FALSE,
NULL); NULL);
data->row_deleted_id = data->row_deleted_id =
@ -936,7 +933,7 @@ register_signals (XedWindow *window,
message = xed_message_type_instantiate (root_changed_type, message = xed_message_type_instantiate (root_changed_type,
"id", NULL, "id", NULL,
"uri", NULL, "location", NULL,
NULL); NULL);
data->root_changed_id = data->root_changed_id =
g_signal_connect_data (store, g_signal_connect_data (store,
@ -948,7 +945,7 @@ register_signals (XedWindow *window,
message = xed_message_type_instantiate (begin_loading_type, message = xed_message_type_instantiate (begin_loading_type,
"id", NULL, "id", NULL,
"uri", NULL, "location", NULL,
NULL); NULL);
data->begin_loading_id = data->begin_loading_id =
g_signal_connect_data (store, g_signal_connect_data (store,
@ -960,7 +957,7 @@ register_signals (XedWindow *window,
message = xed_message_type_instantiate (end_loading_type, message = xed_message_type_instantiate (end_loading_type,
"id", NULL, "id", NULL,
"uri", NULL, "location", NULL,
NULL); NULL);
data->end_loading_id = data->end_loading_id =
g_signal_connect_data (store, g_signal_connect_data (store,

View File

@ -68,8 +68,8 @@ enum
PROP_WINDOW PROP_WINDOW
}; };
static void on_uri_activated_cb (XedFileBrowserWidget *widget, static void on_location_activated_cb (XedFileBrowserWidget *widget,
gchar const *uri, GFile *location,
XedWindow *window); XedWindow *window);
static void on_error_cb (XedFileBrowserWidget *widget, static void on_error_cb (XedFileBrowserWidget *widget,
guint code, guint code,
@ -85,8 +85,8 @@ static void on_filter_mode_changed_cb (XedFileBrowserStore *model,
GParamSpec *param, GParamSpec *param,
XedFileBrowserPlugin *plugin); XedFileBrowserPlugin *plugin);
static void on_rename_cb (XedFileBrowserStore *model, static void on_rename_cb (XedFileBrowserStore *model,
const gchar *olduri, GFile *oldfile,
const gchar *newuri, GFile *newfile,
XedWindow *window); XedWindow *window);
static void on_filter_pattern_changed_cb (XedFileBrowserWidget *widget, static void on_filter_pattern_changed_cb (XedFileBrowserWidget *widget,
GParamSpec *param, GParamSpec *param,
@ -229,25 +229,28 @@ restore_default_location (XedFileBrowserPlugin *plugin)
remote = g_settings_get_boolean (priv->onload_settings, "enable-remote"); remote = g_settings_get_boolean (priv->onload_settings, "enable-remote");
if (root != NULL && *root != '\0') { if (root != NULL && *root != '\0') {
GFile *file; GFile *rootfile;
GFile *vrootfile;
file = g_file_new_for_uri (root); rootfile = g_file_new_for_uri (root);
vrootfile = g_file_new_for_uri (virtual_root);
if (remote || g_file_is_native (file)) if (remote || g_file_is_native (rootfile))
{ {
if (virtual_root != NULL && *virtual_root != '\0') if (virtual_root != NULL && *virtual_root != '\0')
{ {
prepare_auto_root (plugin); prepare_auto_root (plugin);
xed_file_browser_widget_set_root_and_virtual_root (priv->tree_widget, root, virtual_root); xed_file_browser_widget_set_root_and_virtual_root (priv->tree_widget, rootfile, vrootfile);
} }
else else
{ {
prepare_auto_root (plugin); prepare_auto_root (plugin);
xed_file_browser_widget_set_root (priv->tree_widget, root, TRUE); xed_file_browser_widget_set_root (priv->tree_widget, rootfile, TRUE);
} }
} }
g_object_unref (file); g_object_unref (rootfile);
g_object_unref (vrootfile);
} }
g_free (root); g_free (root);
@ -317,16 +320,11 @@ set_root_from_doc (XedFileBrowserPlugin *plugin,
if (parent != NULL) if (parent != NULL)
{ {
gchar * root;
root = g_file_get_uri (parent);
xed_file_browser_widget_set_root (priv->tree_widget, xed_file_browser_widget_set_root (priv->tree_widget,
root, parent,
TRUE); TRUE);
g_object_unref (parent); g_object_unref (parent);
g_free (root);
} }
g_object_unref (file); g_object_unref (file);
@ -352,7 +350,6 @@ on_action_open_terminal (GtkAction *action,
{ {
XedFileBrowserPluginPrivate *priv = plugin->priv; XedFileBrowserPluginPrivate *priv = plugin->priv;
gchar *terminal; gchar *terminal;
gchar *wd = NULL;
gchar *local; gchar *local;
gchar *argv[2]; gchar *argv[2];
GFile *file; GFile *file;
@ -367,18 +364,16 @@ on_action_open_terminal (GtkAction *action,
} }
store = xed_file_browser_widget_get_browser_store (priv->tree_widget); store = xed_file_browser_widget_get_browser_store (priv->tree_widget);
gtk_tree_model_get (GTK_TREE_MODEL (store), &iter, XED_FILE_BROWSER_STORE_COLUMN_URI, &wd, -1); gtk_tree_model_get (GTK_TREE_MODEL (store), &iter, XED_FILE_BROWSER_STORE_COLUMN_LOCATION, &file, -1);
if (wd == NULL) if (file == NULL)
{ {
return; return;
} }
terminal = get_terminal (plugin); terminal = get_terminal (plugin);
file = g_file_new_for_uri (wd);
local = g_file_get_path (file); local = g_file_get_path (file);
g_object_unref (file);
argv[0] = terminal; argv[0] = terminal;
argv[1] = NULL; argv[1] = NULL;
@ -393,7 +388,6 @@ on_action_open_terminal (GtkAction *action,
NULL); NULL);
g_free (terminal); g_free (terminal);
g_free (wd);
g_free (local); g_free (local);
} }
@ -406,7 +400,7 @@ on_selection_changed_cb (GtkTreeSelection *selection,
GtkTreeModel *model; GtkTreeModel *model;
GtkTreeIter iter; GtkTreeIter iter;
gboolean sensitive; gboolean sensitive;
gchar *uri; GFile *location;
tree_view = GTK_TREE_VIEW (xed_file_browser_widget_get_browser_view (priv->tree_widget)); tree_view = GTK_TREE_VIEW (xed_file_browser_widget_get_browser_view (priv->tree_widget));
model = gtk_tree_view_get_model (tree_view); model = gtk_tree_view_get_model (tree_view);
@ -420,10 +414,9 @@ on_selection_changed_cb (GtkTreeSelection *selection,
if (sensitive) if (sensitive)
{ {
gtk_tree_model_get (model, &iter, XED_FILE_BROWSER_STORE_COLUMN_URI, &uri, -1); gtk_tree_model_get (model, &iter, XED_FILE_BROWSER_STORE_COLUMN_LOCATION, &location, -1);
sensitive = xed_utils_uri_has_file_scheme (uri); sensitive = xed_utils_location_has_file_scheme (location);
g_free (uri);
} }
gtk_action_set_sensitive (gtk_action_group_get_action (priv->single_selection_action_group, "OpenTerminal"), sensitive); gtk_action_set_sensitive (gtk_action_group_get_action (priv->single_selection_action_group, "OpenTerminal"), sensitive);
@ -550,8 +543,8 @@ xed_file_browser_plugin_activate (XedWindowActivatable *activatable)
priv->settings = g_settings_new (FILE_BROWSER_SCHEMA); priv->settings = g_settings_new (FILE_BROWSER_SCHEMA);
priv->onload_settings = g_settings_new (FILE_BROWSER_ONLOAD_SCHEMA); priv->onload_settings = g_settings_new (FILE_BROWSER_ONLOAD_SCHEMA);
g_signal_connect (priv->tree_widget, "uri-activated", g_signal_connect (priv->tree_widget, "location-activated",
G_CALLBACK (on_uri_activated_cb), priv->window); G_CALLBACK (on_location_activated_cb), priv->window);
g_signal_connect (priv->tree_widget, "error", g_signal_connect (priv->tree_widget, "error",
G_CALLBACK (on_error_cb), plugin); G_CALLBACK (on_error_cb), plugin);
@ -652,11 +645,11 @@ xed_file_browser_plugin_class_finalize (XedFileBrowserPluginClass *klass)
/* Callbacks */ /* Callbacks */
static void static void
on_uri_activated_cb (XedFileBrowserWidget *tree_widget, on_location_activated_cb (XedFileBrowserWidget *tree_widget,
gchar const *uri, GFile *location,
XedWindow *window) XedWindow *window)
{ {
xed_commands_load_uri (window, uri, NULL, 0); xed_commands_load_location (window, location, NULL, 0);
} }
static void static void
@ -764,8 +757,8 @@ on_filter_mode_changed_cb (XedFileBrowserStore *model,
static void static void
on_rename_cb (XedFileBrowserStore *store, on_rename_cb (XedFileBrowserStore *store,
const gchar *olduri, GFile *oldfile,
const gchar *newuri, GFile *newfile,
XedWindow *window) XedWindow *window)
{ {
XedApp *app; XedApp *app;
@ -773,32 +766,24 @@ on_rename_cb (XedFileBrowserStore *store,
GList *item; GList *item;
XedDocument *doc; XedDocument *doc;
GFile *docfile; GFile *docfile;
GFile *oldfile;
GFile *newfile;
gchar *uri;
/* Find all documents and set its uri to newuri where it matches olduri */ /* Find all documents and set its uri to newuri where it matches olduri */
app = xed_app_get_default (); app = xed_app_get_default ();
documents = xed_app_get_documents (app); documents = xed_app_get_documents (app);
oldfile = g_file_new_for_uri (olduri);
newfile = g_file_new_for_uri (newuri);
for (item = documents; item; item = item->next) for (item = documents; item; item = item->next)
{ {
doc = XED_DOCUMENT (item->data); doc = XED_DOCUMENT (item->data);
uri = xed_document_get_uri (doc); docfile = xed_document_get_location (doc);
if (!uri) if (!docfile)
{ {
continue; continue;
} }
docfile = g_file_new_for_uri (uri);
if (g_file_equal (docfile, oldfile)) if (g_file_equal (docfile, oldfile))
{ {
xed_document_set_uri (doc, newuri); xed_document_set_location (doc, newfile);
} }
else else
{ {
@ -812,24 +797,18 @@ on_rename_cb (XedFileBrowserStore *store,
the prefix oldfile */ the prefix oldfile */
g_object_unref (docfile); g_object_unref (docfile);
g_free (uri);
docfile = g_file_get_child (newfile, relative); docfile = g_file_get_child (newfile, relative);
uri = g_file_get_uri (docfile);
xed_document_set_uri (doc, uri); xed_document_set_location (doc, docfile);
} }
g_free (relative); g_free (relative);
} }
g_free (uri);
g_object_unref (docfile); g_object_unref (docfile);
} }
g_object_unref (oldfile);
g_object_unref (newfile);
g_list_free (documents); g_list_free (documents);
} }
@ -861,8 +840,9 @@ on_virtual_root_changed_cb (XedFileBrowserStore *store,
XedFileBrowserPlugin *plugin) XedFileBrowserPlugin *plugin)
{ {
XedFileBrowserPluginPrivate *priv = plugin->priv; XedFileBrowserPluginPrivate *priv = plugin->priv;
gchar * root; GFile *root;
gchar * virtual_root; GFile *virtual_root;
gchar *uri_root = NULL;
root = xed_file_browser_store_get_root (store); root = xed_file_browser_store_get_root (store);
@ -870,25 +850,35 @@ on_virtual_root_changed_cb (XedFileBrowserStore *store,
{ {
return; return;
} }
else
{
uri_root = g_file_get_uri (root);
g_object_unref (root);
}
g_settings_set_string (priv->onload_settings, "root", root); g_settings_set_string (priv->onload_settings, "root", uri_root);
g_free (uri_root);
virtual_root = xed_file_browser_store_get_virtual_root (store); virtual_root = xed_file_browser_store_get_virtual_root (store);
if (!virtual_root) if (!virtual_root)
{ {
/* Set virtual to same as root then */ /* Set virtual to same as root then */
g_settings_set_string (priv->onload_settings, "virtual-root", root); g_settings_set_string (priv->onload_settings, "virtual-root", uri_root);
} }
else else
{ {
g_settings_set_string (priv->onload_settings, "virtual-root", virtual_root); gchar *uri_vroot;
uri_vroot = g_file_get_uri (virtual_root);
g_settings_set_string (priv->onload_settings, "virtual-root", uri_vroot);
g_free (uri_vroot);
g_object_unref (virtual_root);
} }
g_signal_handlers_disconnect_by_func (XED_WINDOW (priv->window), G_CALLBACK (on_tab_added_cb), plugin); g_signal_handlers_disconnect_by_func (XED_WINDOW (priv->window), G_CALLBACK (on_tab_added_cb), plugin);
g_free (root);
g_free (virtual_root);
} }
static void static void
@ -905,23 +895,27 @@ on_tab_added_cb (XedWindow *window,
if (open) if (open)
{ {
XedDocument *doc; XedDocument *doc;
gchar *uri; GFile *location;
doc = xed_tab_get_document (tab); doc = xed_tab_get_document (tab);
uri = xed_document_get_uri (doc); location = xed_document_get_location (doc);
if (uri != NULL && xed_utils_uri_has_file_scheme (uri)) if (location != NULL)
{
if (xed_utils_location_has_file_scheme (location))
{ {
prepare_auto_root (plugin); prepare_auto_root (plugin);
set_root_from_doc (plugin, doc); set_root_from_doc (plugin, doc);
load_default = FALSE; load_default = FALSE;
} }
g_object_unref (location);
g_free (uri); }
} }
if (load_default) if (load_default)
{
restore_default_location (plugin); restore_default_location (plugin);
}
/* Disconnect this signal, it's only called once */ /* Disconnect this signal, it's only called once */
g_signal_handlers_disconnect_by_func (window, G_CALLBACK (on_tab_added_cb), plugin); g_signal_handlers_disconnect_by_func (window, G_CALLBACK (on_tab_added_cb), plugin);
@ -932,12 +926,12 @@ get_filename_from_path (GtkTreeModel *model,
GtkTreePath *path) GtkTreePath *path)
{ {
GtkTreeIter iter; GtkTreeIter iter;
gchar *uri; GFile *location;
gtk_tree_model_get_iter (model, &iter, path); gtk_tree_model_get_iter (model, &iter, path);
gtk_tree_model_get (model, &iter, XED_FILE_BROWSER_STORE_COLUMN_URI, &uri, -1); gtk_tree_model_get (model, &iter, XED_FILE_BROWSER_STORE_COLUMN_LOCATION, &location, -1);
return xed_file_browser_utils_uri_basename (uri); return xed_file_browser_utils_file_basename (location);
} }
static gboolean static gboolean

View File

@ -81,7 +81,7 @@ struct _AsyncNode
typedef struct { typedef struct {
XedFileBrowserStore *model; XedFileBrowserStore *model;
gchar *virtual_root; GFile *virtual_root;
GMountOperation *operation; GMountOperation *operation;
GCancellable *cancellable; GCancellable *cancellable;
} MountInfo; } MountInfo;
@ -267,16 +267,13 @@ static void
set_gvalue_from_node (GValue *value, set_gvalue_from_node (GValue *value,
FileBrowserNode *node) FileBrowserNode *node)
{ {
gchar * uri; if (node == NULL)
if (node == NULL || !node->file)
{ {
g_value_set_string (value, NULL); g_value_set_object (value, NULL);
} }
else else
{ {
uri = g_file_get_uri (node->file); g_value_set_object (value, node->file);
g_value_take_string (value, uri);
} }
} }
@ -335,17 +332,17 @@ xed_file_browser_store_class_init (XedFileBrowserStoreClass * klass)
object_class->set_property = xed_file_browser_store_set_property; object_class->set_property = xed_file_browser_store_set_property;
g_object_class_install_property (object_class, PROP_ROOT, g_object_class_install_property (object_class, PROP_ROOT,
g_param_spec_string ("root", g_param_spec_object ("root",
"Root", "Root",
"The root uri", "The root location",
NULL, G_TYPE_FILE,
G_PARAM_READABLE)); G_PARAM_READABLE));
g_object_class_install_property (object_class, PROP_VIRTUAL_ROOT, g_object_class_install_property (object_class, PROP_VIRTUAL_ROOT,
g_param_spec_string ("virtual-root", g_param_spec_object ("virtual-root",
"Virtual Root", "Virtual Root",
"The virtual root uri", "The virtual root location",
NULL, G_TYPE_FILE,
G_PARAM_READABLE)); G_PARAM_READABLE));
g_object_class_install_property (object_class, PROP_FILTER_MODE, g_object_class_install_property (object_class, PROP_FILTER_MODE,
@ -394,10 +391,10 @@ xed_file_browser_store_class_init (XedFileBrowserStoreClass * klass)
G_SIGNAL_RUN_LAST, G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (XedFileBrowserStoreClass, G_STRUCT_OFFSET (XedFileBrowserStoreClass,
rename), NULL, NULL, rename), NULL, NULL,
xed_file_browser_marshal_VOID__STRING_STRING, xed_file_browser_marshal_VOID__OBJECT_OBJECT,
G_TYPE_NONE, 2, G_TYPE_NONE, 2,
G_TYPE_STRING, G_TYPE_FILE,
G_TYPE_STRING); G_TYPE_FILE);
model_signals[BEGIN_REFRESH] = model_signals[BEGIN_REFRESH] =
g_signal_new ("begin-refresh", g_signal_new ("begin-refresh",
G_OBJECT_CLASS_TYPE (object_class), G_OBJECT_CLASS_TYPE (object_class),
@ -420,9 +417,9 @@ xed_file_browser_store_class_init (XedFileBrowserStoreClass * klass)
G_SIGNAL_RUN_LAST, G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (XedFileBrowserStoreClass, G_STRUCT_OFFSET (XedFileBrowserStoreClass,
unload), NULL, NULL, unload), NULL, NULL,
g_cclosure_marshal_VOID__STRING, g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE, 1, G_TYPE_NONE, 1,
G_TYPE_STRING); G_TYPE_FILE);
g_type_class_add_private (object_class, sizeof (XedFileBrowserStorePrivate)); g_type_class_add_private (object_class, sizeof (XedFileBrowserStorePrivate));
} }
@ -464,7 +461,7 @@ xed_file_browser_store_init (XedFileBrowserStore * obj)
{ {
obj->priv = XED_FILE_BROWSER_STORE_GET_PRIVATE (obj); obj->priv = XED_FILE_BROWSER_STORE_GET_PRIVATE (obj);
obj->priv->column_types[XED_FILE_BROWSER_STORE_COLUMN_URI] = G_TYPE_STRING; obj->priv->column_types[XED_FILE_BROWSER_STORE_COLUMN_LOCATION] = G_TYPE_FILE;
obj->priv->column_types[XED_FILE_BROWSER_STORE_COLUMN_NAME] = G_TYPE_STRING; obj->priv->column_types[XED_FILE_BROWSER_STORE_COLUMN_NAME] = G_TYPE_STRING;
obj->priv->column_types[XED_FILE_BROWSER_STORE_COLUMN_FLAGS] = G_TYPE_UINT; obj->priv->column_types[XED_FILE_BROWSER_STORE_COLUMN_FLAGS] = G_TYPE_UINT;
obj->priv->column_types[XED_FILE_BROWSER_STORE_COLUMN_ICON] = GDK_TYPE_PIXBUF; obj->priv->column_types[XED_FILE_BROWSER_STORE_COLUMN_ICON] = GDK_TYPE_PIXBUF;
@ -713,7 +710,7 @@ xed_file_browser_store_get_value (GtkTreeModel *tree_model,
switch (column) switch (column)
{ {
case XED_FILE_BROWSER_STORE_COLUMN_URI: case XED_FILE_BROWSER_STORE_COLUMN_LOCATION:
set_gvalue_from_node (value, node); set_gvalue_from_node (value, node);
break; break;
case XED_FILE_BROWSER_STORE_COLUMN_NAME: case XED_FILE_BROWSER_STORE_COLUMN_NAME:
@ -1013,7 +1010,7 @@ xed_file_browser_store_drag_data_get (GtkTreeDragSource *drag_source,
GtkSelectionData *selection_data) GtkSelectionData *selection_data)
{ {
GtkTreeIter iter; GtkTreeIter iter;
gchar *uri; GFile *location;
gchar *uris[2] = {0, }; gchar *uris[2] = {0, };
gboolean ret; gboolean ret;
@ -1022,14 +1019,14 @@ xed_file_browser_store_drag_data_get (GtkTreeDragSource *drag_source,
return FALSE; return FALSE;
} }
gtk_tree_model_get (GTK_TREE_MODEL (drag_source), &iter, XED_FILE_BROWSER_STORE_COLUMN_URI, &uri, -1); gtk_tree_model_get (GTK_TREE_MODEL (drag_source), &iter, XED_FILE_BROWSER_STORE_COLUMN_LOCATION, &location, -1);
g_assert (uri); g_assert (location);
uris[0] = uri; uris[0] = g_file_get_uri (location);
ret = gtk_selection_data_set_uris (selection_data, uris); ret = gtk_selection_data_set_uris (selection_data, uris);
g_free (uri); g_free (uris[0]);
return ret; return ret;
} }
@ -1448,8 +1445,6 @@ static void
file_browser_node_free (XedFileBrowserStore *model, file_browser_node_free (XedFileBrowserStore *model,
FileBrowserNode *node) FileBrowserNode *node)
{ {
gchar *uri;
if (node == NULL) if (node == NULL)
{ {
return; return;
@ -1485,10 +1480,7 @@ file_browser_node_free (XedFileBrowserStore *model,
if (node->file) if (node->file)
{ {
uri = g_file_get_uri (node->file); g_signal_emit (model, model_signals[UNLOAD], 0, node->file);
g_signal_emit (model, model_signals[UNLOAD], 0, uri);
g_free (uri);
g_object_unref (node->file); g_object_unref (node->file);
} }
@ -2940,14 +2932,14 @@ unique_new_name (GFile *directory,
static XedFileBrowserStoreResult static XedFileBrowserStoreResult
model_root_mounted (XedFileBrowserStore *model, model_root_mounted (XedFileBrowserStore *model,
gchar const *virtual_root) GFile *virtual_root)
{ {
model_check_dummy (model, model->priv->root); model_check_dummy (model, model->priv->root);
g_object_notify (G_OBJECT (model), "root"); g_object_notify (G_OBJECT (model), "root");
if (virtual_root != NULL) if (virtual_root != NULL)
{ {
return xed_file_browser_store_set_virtual_root_from_string (model, virtual_root); return xed_file_browser_store_set_virtual_root_from_location (model, virtual_root);
} }
else else
{ {
@ -3028,7 +3020,7 @@ mount_cb (GFile *file,
static XedFileBrowserStoreResult static XedFileBrowserStoreResult
model_mount_root (XedFileBrowserStore *model, model_mount_root (XedFileBrowserStore *model,
gchar const *virtual_root) GFile *virtual_root)
{ {
GFileInfo *info; GFileInfo *info;
GError *error = NULL; GError *error = NULL;
@ -3049,7 +3041,7 @@ model_mount_root (XedFileBrowserStore *model,
mount_info = g_new(MountInfo, 1); mount_info = g_new(MountInfo, 1);
mount_info->model = model; mount_info->model = model;
mount_info->virtual_root = g_strdup (virtual_root); mount_info->virtual_root = g_file_dup (virtual_root);
/* FIXME: we should be setting the correct window */ /* FIXME: we should be setting the correct window */
mount_info->operation = gtk_mount_operation_new (NULL); mount_info->operation = gtk_mount_operation_new (NULL);
@ -3085,7 +3077,7 @@ model_mount_root (XedFileBrowserStore *model,
/* Public */ /* Public */
XedFileBrowserStore * XedFileBrowserStore *
xed_file_browser_store_new (gchar const *root) xed_file_browser_store_new (GFile *root)
{ {
XedFileBrowserStore *obj = XED_FILE_BROWSER_STORE (g_object_new (XED_TYPE_FILE_BROWSER_STORE, NULL)); XedFileBrowserStore *obj = XED_FILE_BROWSER_STORE (g_object_new (XED_TYPE_FILE_BROWSER_STORE, NULL));
@ -3156,56 +3148,52 @@ xed_file_browser_store_set_virtual_root (XedFileBrowserStore *model,
} }
XedFileBrowserStoreResult XedFileBrowserStoreResult
xed_file_browser_store_set_virtual_root_from_string (XedFileBrowserStore *model, xed_file_browser_store_set_virtual_root_from_location (XedFileBrowserStore *model,
gchar const *root) GFile *root)
{ {
GFile *file;
g_return_val_if_fail (XED_IS_FILE_BROWSER_STORE (model), XED_FILE_BROWSER_STORE_RESULT_NO_CHANGE); g_return_val_if_fail (XED_IS_FILE_BROWSER_STORE (model), XED_FILE_BROWSER_STORE_RESULT_NO_CHANGE);
file = g_file_new_for_uri (root); if (root == NULL)
if (file == NULL)
{ {
g_warning ("Invalid uri (%s)", root); gchar *uri;
uri = g_file_get_uri (root);
g_warning ("Invalid uri (%s)", uri);
g_free (uri);
return XED_FILE_BROWSER_STORE_RESULT_NO_CHANGE; return XED_FILE_BROWSER_STORE_RESULT_NO_CHANGE;
} }
/* Check if uri is already the virtual root */ /* Check if uri is already the virtual root */
if (model->priv->virtual_root && g_file_equal (model->priv->virtual_root->file, file)) if (model->priv->virtual_root && g_file_equal (model->priv->virtual_root->file, root))
{ {
g_object_unref (file);
return XED_FILE_BROWSER_STORE_RESULT_NO_CHANGE; return XED_FILE_BROWSER_STORE_RESULT_NO_CHANGE;
} }
/* Check if uri is the root itself */ /* Check if uri is the root itself */
if (g_file_equal (model->priv->root->file, file)) if (g_file_equal (model->priv->root->file, root))
{ {
g_object_unref (file);
/* Always clear the model before altering the nodes */ /* Always clear the model before altering the nodes */
model_clear (model, FALSE); model_clear (model, FALSE);
set_virtual_root_from_node (model, model->priv->root); set_virtual_root_from_node (model, model->priv->root);
return XED_FILE_BROWSER_STORE_RESULT_OK; return XED_FILE_BROWSER_STORE_RESULT_OK;
} }
if (!g_file_has_prefix (file, model->priv->root->file)) if (!g_file_has_prefix (root, model->priv->root->file))
{ {
gchar *str, *str1; gchar *str, *str1;
str = g_file_get_parse_name (model->priv->root->file); str = g_file_get_parse_name (model->priv->root->file);
str1 = g_file_get_parse_name (file); str1 = g_file_get_parse_name (root);
g_warning ("Virtual root (%s) is not below actual root (%s)", str1, str); g_warning ("Virtual root (%s) is not below actual root (%s)", str1, str);
g_free (str); g_free (str);
g_free (str1); g_free (str1);
g_object_unref (file);
return XED_FILE_BROWSER_STORE_RESULT_ERROR; return XED_FILE_BROWSER_STORE_RESULT_ERROR;
} }
set_virtual_root_from_file (model, file); set_virtual_root_from_file (model, root);
g_object_unref (file);
return XED_FILE_BROWSER_STORE_RESULT_OK; return XED_FILE_BROWSER_STORE_RESULT_OK;
} }
@ -3298,11 +3286,9 @@ xed_file_browser_store_cancel_mount_operation (XedFileBrowserStore *store)
XedFileBrowserStoreResult XedFileBrowserStoreResult
xed_file_browser_store_set_root_and_virtual_root (XedFileBrowserStore *model, xed_file_browser_store_set_root_and_virtual_root (XedFileBrowserStore *model,
gchar const *root, GFile *root,
gchar const *virtual_root) GFile *virtual_root)
{ {
GFile * file = NULL;
GFile * vfile = NULL;
FileBrowserNode * node; FileBrowserNode * node;
gboolean equal = FALSE; gboolean equal = FALSE;
@ -3313,38 +3299,22 @@ xed_file_browser_store_set_root_and_virtual_root (XedFileBrowserStore *model,
return XED_FILE_BROWSER_STORE_RESULT_NO_CHANGE; return XED_FILE_BROWSER_STORE_RESULT_NO_CHANGE;
} }
if (root != NULL)
{
file = g_file_new_for_uri (root);
}
if (root != NULL && model->priv->root != NULL) if (root != NULL && model->priv->root != NULL)
{ {
equal = g_file_equal (file, model->priv->root->file); equal = g_file_equal (root, model->priv->root->file);
if (equal && virtual_root == NULL) if (equal && virtual_root == NULL)
{ {
g_object_unref (file);
return XED_FILE_BROWSER_STORE_RESULT_NO_CHANGE; return XED_FILE_BROWSER_STORE_RESULT_NO_CHANGE;
} }
} }
if (virtual_root) if (virtual_root)
{ {
vfile = g_file_new_for_uri (virtual_root); if (equal && g_file_equal (virtual_root, model->priv->virtual_root->file))
if (equal && g_file_equal (vfile, model->priv->virtual_root->file))
{ {
if (file)
{
g_object_unref (file);
}
g_object_unref (vfile);
return XED_FILE_BROWSER_STORE_RESULT_NO_CHANGE; return XED_FILE_BROWSER_STORE_RESULT_NO_CHANGE;
} }
g_object_unref (vfile);
} }
/* make sure to cancel any previous mount operations */ /* make sure to cancel any previous mount operations */
@ -3357,12 +3327,10 @@ xed_file_browser_store_set_root_and_virtual_root (XedFileBrowserStore *model,
model->priv->root = NULL; model->priv->root = NULL;
model->priv->virtual_root = NULL; model->priv->virtual_root = NULL;
if (file != NULL) if (root != NULL)
{ {
/* Create the root node */ /* Create the root node */
node = file_browser_node_dir_new (model, file, NULL); node = file_browser_node_dir_new (model, root, NULL);
g_object_unref (file);
model->priv->root = node; model->priv->root = node;
return model_mount_root (model, virtual_root); return model_mount_root (model, virtual_root);
@ -3378,13 +3346,13 @@ xed_file_browser_store_set_root_and_virtual_root (XedFileBrowserStore *model,
XedFileBrowserStoreResult XedFileBrowserStoreResult
xed_file_browser_store_set_root (XedFileBrowserStore *model, xed_file_browser_store_set_root (XedFileBrowserStore *model,
gchar const *root) GFile *root)
{ {
g_return_val_if_fail (XED_IS_FILE_BROWSER_STORE (model), XED_FILE_BROWSER_STORE_RESULT_NO_CHANGE); g_return_val_if_fail (XED_IS_FILE_BROWSER_STORE (model), XED_FILE_BROWSER_STORE_RESULT_NO_CHANGE);
return xed_file_browser_store_set_root_and_virtual_root (model, root, NULL); return xed_file_browser_store_set_root_and_virtual_root (model, root, NULL);
} }
gchar * GFile *
xed_file_browser_store_get_root (XedFileBrowserStore * model) xed_file_browser_store_get_root (XedFileBrowserStore * model)
{ {
g_return_val_if_fail (XED_IS_FILE_BROWSER_STORE (model), NULL); g_return_val_if_fail (XED_IS_FILE_BROWSER_STORE (model), NULL);
@ -3395,11 +3363,11 @@ xed_file_browser_store_get_root (XedFileBrowserStore * model)
} }
else else
{ {
return g_file_get_uri (model->priv->root->file); return g_file_dup (model->priv->root->file);
} }
} }
gchar * GFile *
xed_file_browser_store_get_virtual_root (XedFileBrowserStore *model) xed_file_browser_store_get_virtual_root (XedFileBrowserStore *model)
{ {
g_return_val_if_fail (XED_IS_FILE_BROWSER_STORE (model), NULL); g_return_val_if_fail (XED_IS_FILE_BROWSER_STORE (model), NULL);
@ -3410,7 +3378,7 @@ xed_file_browser_store_get_virtual_root (XedFileBrowserStore *model)
} }
else else
{ {
return g_file_get_uri (model->priv->virtual_root->file); return g_file_dup (model->priv->virtual_root->file);
} }
} }
@ -3573,8 +3541,6 @@ xed_file_browser_store_rename (XedFileBrowserStore *model,
GFile *parent; GFile *parent;
GFile *previous; GFile *previous;
GError *err = NULL; GError *err = NULL;
gchar *olduri;
gchar *newuri;
GtkTreePath *path; GtkTreePath *path;
g_return_val_if_fail (XED_IS_FILE_BROWSER_STORE (model), FALSE); g_return_val_if_fail (XED_IS_FILE_BROWSER_STORE (model), FALSE);
@ -3628,14 +3594,9 @@ xed_file_browser_store_rename (XedFileBrowserStore *model,
return FALSE; return FALSE;
} }
olduri = g_file_get_uri (previous); g_signal_emit (model, model_signals[RENAME], 0, previous, node->file);
newuri = g_file_get_uri (node->file);
g_signal_emit (model, model_signals[RENAME], 0, olduri, newuri);
g_object_unref (previous); g_object_unref (previous);
g_free (olduri);
g_free (newuri);
return TRUE; return TRUE;
} }

View File

@ -37,7 +37,7 @@ typedef enum
{ {
XED_FILE_BROWSER_STORE_COLUMN_ICON = 0, XED_FILE_BROWSER_STORE_COLUMN_ICON = 0,
XED_FILE_BROWSER_STORE_COLUMN_NAME, XED_FILE_BROWSER_STORE_COLUMN_NAME,
XED_FILE_BROWSER_STORE_COLUMN_URI, XED_FILE_BROWSER_STORE_COLUMN_LOCATION,
XED_FILE_BROWSER_STORE_COLUMN_FLAGS, XED_FILE_BROWSER_STORE_COLUMN_FLAGS,
XED_FILE_BROWSER_STORE_COLUMN_EMBLEM, XED_FILE_BROWSER_STORE_COLUMN_EMBLEM,
XED_FILE_BROWSER_STORE_COLUMN_NUM XED_FILE_BROWSER_STORE_COLUMN_NUM
@ -106,28 +106,28 @@ struct _XedFileBrowserStoreClass {
gboolean (*no_trash) (XedFileBrowserStore *model, gboolean (*no_trash) (XedFileBrowserStore *model,
GList *files); GList *files);
void (*rename) (XedFileBrowserStore *model, void (*rename) (XedFileBrowserStore *model,
const gchar *olduri, GFile *oldfile,
const gchar *newuri); GFile *newfile);
void (*begin_refresh) (XedFileBrowserStore *model); void (*begin_refresh) (XedFileBrowserStore *model);
void (*end_refresh) (XedFileBrowserStore *model); void (*end_refresh) (XedFileBrowserStore *model);
void (*unload) (XedFileBrowserStore *model, void (*unload) (XedFileBrowserStore *model,
const gchar *uri); GFile *location);
}; };
GType xed_file_browser_store_get_type (void) G_GNUC_CONST; GType xed_file_browser_store_get_type (void) G_GNUC_CONST;
void _xed_file_browser_store_register_type (GTypeModule *type_module); void _xed_file_browser_store_register_type (GTypeModule *type_module);
XedFileBrowserStore *xed_file_browser_store_new (gchar const *root); XedFileBrowserStore *xed_file_browser_store_new (GFile *root);
XedFileBrowserStoreResult xed_file_browser_store_set_root_and_virtual_root (XedFileBrowserStore *model, XedFileBrowserStoreResult xed_file_browser_store_set_root_and_virtual_root (XedFileBrowserStore *model,
gchar const *root, GFile *root,
gchar const *virtual_root); GFile *virtual_root);
XedFileBrowserStoreResult xed_file_browser_store_set_root (XedFileBrowserStore *model, XedFileBrowserStoreResult xed_file_browser_store_set_root (XedFileBrowserStore *model,
gchar const *root); GFile *root);
XedFileBrowserStoreResult xed_file_browser_store_set_virtual_root (XedFileBrowserStore *model, XedFileBrowserStoreResult xed_file_browser_store_set_virtual_root (XedFileBrowserStore *model,
GtkTreeIter *iter); GtkTreeIter *iter);
XedFileBrowserStoreResult xed_file_browser_store_set_virtual_root_from_string (XedFileBrowserStore *model, XedFileBrowserStoreResult xed_file_browser_store_set_virtual_root_from_location (XedFileBrowserStore *model,
gchar const *root); GFile *root);
XedFileBrowserStoreResult xed_file_browser_store_set_virtual_root_up (XedFileBrowserStore *model); XedFileBrowserStoreResult xed_file_browser_store_set_virtual_root_up (XedFileBrowserStore *model);
XedFileBrowserStoreResult xed_file_browser_store_set_virtual_root_top (XedFileBrowserStore *model); XedFileBrowserStoreResult xed_file_browser_store_set_virtual_root_top (XedFileBrowserStore *model);
@ -135,8 +135,8 @@ gboolean xed_file_browser_store_get_iter_virtual_root (XedFileBrowserStore *mode
GtkTreeIter *iter); GtkTreeIter *iter);
gboolean xed_file_browser_store_get_iter_root (XedFileBrowserStore *model, gboolean xed_file_browser_store_get_iter_root (XedFileBrowserStore *model,
GtkTreeIter *iter); GtkTreeIter *iter);
gchar * xed_file_browser_store_get_root (XedFileBrowserStore *model); GFile * xed_file_browser_store_get_root (XedFileBrowserStore *model);
gchar * xed_file_browser_store_get_virtual_root (XedFileBrowserStore *model); GFile * xed_file_browser_store_get_virtual_root (XedFileBrowserStore *model);
gboolean xed_file_browser_store_iter_equal (XedFileBrowserStore *model, gboolean xed_file_browser_store_iter_equal (XedFileBrowserStore *model,
GtkTreeIter *iter1, GtkTreeIter *iter1,

View File

@ -128,20 +128,7 @@ xed_file_browser_utils_pixbuf_from_file (GFile * file,
gchar * gchar *
xed_file_browser_utils_file_basename (GFile * file) xed_file_browser_utils_file_basename (GFile * file)
{ {
gchar *uri; return xed_utils_basename_for_display (file);
gchar *ret;
uri = g_file_get_uri (file);
ret = xed_file_browser_utils_uri_basename (uri);
g_free (uri);
return ret;
}
gchar *
xed_file_browser_utils_uri_basename (gchar const * uri)
{
return xed_utils_basename_for_display (uri);
} }
gboolean gboolean

View File

@ -13,7 +13,6 @@ GdkPixbuf *xed_file_browser_utils_pixbuf_from_file (GFile * file,
GtkIconSize size); GtkIconSize size);
gchar * xed_file_browser_utils_file_basename (GFile * file); gchar * xed_file_browser_utils_file_basename (GFile * file);
gchar * xed_file_browser_utils_uri_basename (gchar const * uri);
gboolean xed_file_browser_utils_confirmation_dialog (XedWindow * window, gboolean xed_file_browser_utils_confirmation_dialog (XedWindow * window,
GtkMessageType type, GtkMessageType type,

View File

@ -99,7 +99,7 @@ static void on_end_refresh (XedFileBrowserStore *model,
XedFileBrowserView *view); XedFileBrowserView *view);
static void on_unload (XedFileBrowserStore *model, static void on_unload (XedFileBrowserStore *model,
gchar const *uri, GFile *location,
XedFileBrowserView *view); XedFileBrowserView *view);
static void on_row_inserted (XedFileBrowserStore *model, static void on_row_inserted (XedFileBrowserStore *model,
@ -135,46 +135,32 @@ xed_file_browser_view_finalize (GObject *object)
static void static void
add_expand_state (XedFileBrowserView *view, add_expand_state (XedFileBrowserView *view,
gchar const *uri) GFile *location)
{ {
GFile * file; if (!location)
if (!uri)
{ {
return; return;
} }
file = g_file_new_for_uri (uri);
if (view->priv->expand_state) if (view->priv->expand_state)
{ {
g_hash_table_insert (view->priv->expand_state, file, file); g_hash_table_insert (view->priv->expand_state, location, g_object_ref (location));
}
else
{
g_object_unref (file);
} }
} }
static void static void
remove_expand_state (XedFileBrowserView *view, remove_expand_state (XedFileBrowserView *view,
gchar const *uri) GFile *location)
{ {
GFile * file; if (!location)
if (!uri)
{ {
return; return;
} }
file = g_file_new_for_uri (uri);
if (view->priv->expand_state) if (view->priv->expand_state)
{ {
g_hash_table_remove (view->priv->expand_state, file); g_hash_table_remove (view->priv->expand_state, location);
} }
g_object_unref (file);
} }
static void static void
@ -183,7 +169,7 @@ row_expanded (GtkTreeView *tree_view,
GtkTreePath *path) GtkTreePath *path)
{ {
XedFileBrowserView *view = XED_FILE_BROWSER_VIEW (tree_view); XedFileBrowserView *view = XED_FILE_BROWSER_VIEW (tree_view);
gchar *uri; GFile *location;
if (GTK_TREE_VIEW_CLASS (xed_file_browser_view_parent_class)->row_expanded) if (GTK_TREE_VIEW_CLASS (xed_file_browser_view_parent_class)->row_expanded)
{ {
@ -197,10 +183,9 @@ row_expanded (GtkTreeView *tree_view,
if (view->priv->restore_expand_state) if (view->priv->restore_expand_state)
{ {
gtk_tree_model_get (view->priv->model, iter, XED_FILE_BROWSER_STORE_COLUMN_URI, &uri, -1); gtk_tree_model_get (view->priv->model, iter, XED_FILE_BROWSER_STORE_COLUMN_LOCATION, &location, -1);
add_expand_state (view, uri); add_expand_state (view, location);
g_free (uri);
} }
_xed_file_browser_store_iter_expanded (XED_FILE_BROWSER_STORE (view->priv->model), iter); _xed_file_browser_store_iter_expanded (XED_FILE_BROWSER_STORE (view->priv->model), iter);
@ -212,7 +197,7 @@ row_collapsed (GtkTreeView *tree_view,
GtkTreePath *path) GtkTreePath *path)
{ {
XedFileBrowserView *view = XED_FILE_BROWSER_VIEW (tree_view); XedFileBrowserView *view = XED_FILE_BROWSER_VIEW (tree_view);
gchar * uri; GFile *location;
if (GTK_TREE_VIEW_CLASS (xed_file_browser_view_parent_class)->row_collapsed) if (GTK_TREE_VIEW_CLASS (xed_file_browser_view_parent_class)->row_collapsed)
{ {
@ -226,10 +211,9 @@ row_collapsed (GtkTreeView *tree_view,
if (view->priv->restore_expand_state) if (view->priv->restore_expand_state)
{ {
gtk_tree_model_get (view->priv->model, iter, XED_FILE_BROWSER_STORE_COLUMN_URI, &uri, -1); gtk_tree_model_get (view->priv->model, iter, XED_FILE_BROWSER_STORE_COLUMN_LOCATION, &location, -1);
remove_expand_state (view, uri); remove_expand_state (view, location);
g_free (uri);
} }
_xed_file_browser_store_iter_collapsed (XED_FILE_BROWSER_STORE (view->priv->model), iter); _xed_file_browser_store_iter_collapsed (XED_FILE_BROWSER_STORE (view->priv->model), iter);
@ -766,7 +750,7 @@ fill_expand_state (XedFileBrowserView *view,
{ {
GtkTreePath * path; GtkTreePath * path;
GtkTreeIter child; GtkTreeIter child;
gchar * uri; GFile *location;
if (!gtk_tree_model_iter_has_child (view->priv->model, iter)) if (!gtk_tree_model_iter_has_child (view->priv->model, iter))
{ {
@ -779,12 +763,11 @@ fill_expand_state (XedFileBrowserView *view,
{ {
gtk_tree_model_get (view->priv->model, gtk_tree_model_get (view->priv->model,
iter, iter,
XED_FILE_BROWSER_STORE_COLUMN_URI, XED_FILE_BROWSER_STORE_COLUMN_LOCATION,
&uri, &location,
-1); -1);
add_expand_state (view, uri); add_expand_state (view, location);
g_free (uri);
} }
if (gtk_tree_model_iter_children (view->priv->model, &child, iter)) if (gtk_tree_model_iter_children (view->priv->model, &child, iter))
@ -1273,7 +1256,7 @@ on_end_refresh (XedFileBrowserStore *model,
static void static void
on_unload (XedFileBrowserStore *model, on_unload (XedFileBrowserStore *model,
gchar const *uri, GFile *location,
XedFileBrowserView *view) XedFileBrowserView *view)
{ {
/* Don't remove the expand state if we are refreshing */ /* Don't remove the expand state if we are refreshing */
@ -1282,7 +1265,7 @@ on_unload (XedFileBrowserStore *model,
return; return;
} }
remove_expand_state (view, uri); remove_expand_state (view, location);
} }
static void static void
@ -1290,33 +1273,28 @@ restore_expand_state (XedFileBrowserView *view,
XedFileBrowserStore *model, XedFileBrowserStore *model,
GtkTreeIter *iter) GtkTreeIter *iter)
{ {
gchar *uri; GFile *location;
GFile *file;
GtkTreePath *path; GtkTreePath *path;
gtk_tree_model_get (GTK_TREE_MODEL (model), gtk_tree_model_get (GTK_TREE_MODEL (model),
iter, iter,
XED_FILE_BROWSER_STORE_COLUMN_URI, XED_FILE_BROWSER_STORE_COLUMN_LOCATION,
&uri, &location,
-1); -1);
if (!uri) if (!location)
{ {
return; return;
} }
file = g_file_new_for_uri (uri);
path = gtk_tree_model_get_path (GTK_TREE_MODEL (model), iter); path = gtk_tree_model_get_path (GTK_TREE_MODEL (model), iter);
if (g_hash_table_lookup (view->priv->expand_state, file)) if (g_hash_table_lookup (view->priv->expand_state, location))
{ {
gtk_tree_view_expand_row (GTK_TREE_VIEW (view), path, FALSE); gtk_tree_view_expand_row (GTK_TREE_VIEW (view), path, FALSE);
} }
gtk_tree_path_free (path); gtk_tree_path_free (path);
g_object_unref (file);
g_free (uri);
} }
static void static void

View File

@ -80,7 +80,7 @@ enum
/* Signals */ /* Signals */
enum enum
{ {
URI_ACTIVATED, LOCATION_ACTIVATED,
ERROR, ERROR,
CONFIRM_DELETE, CONFIRM_DELETE,
CONFIRM_NO_TRASH, CONFIRM_NO_TRASH,
@ -433,14 +433,14 @@ xed_file_browser_widget_class_init (XedFileBrowserWidgetClass * klass)
G_PARAM_READWRITE | G_PARAM_READWRITE |
G_PARAM_CONSTRUCT)); G_PARAM_CONSTRUCT));
signals[URI_ACTIVATED] = signals[LOCATION_ACTIVATED] =
g_signal_new ("uri-activated", g_signal_new ("location-activated",
G_OBJECT_CLASS_TYPE (object_class), G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_LAST, G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (XedFileBrowserWidgetClass, G_STRUCT_OFFSET (XedFileBrowserWidgetClass,
uri_activated), NULL, NULL, location_activated), NULL, NULL,
g_cclosure_marshal_VOID__STRING, G_TYPE_NONE, 1, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1,
G_TYPE_STRING); G_TYPE_FILE);
signals[ERROR] = signals[ERROR] =
g_signal_new ("error", G_OBJECT_CLASS_TYPE (object_class), g_signal_new ("error", G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_LAST, G_SIGNAL_RUN_LAST,
@ -1060,22 +1060,18 @@ add_bookmark_hash (XedFileBrowserWidget * obj,
GtkTreeModel *model; GtkTreeModel *model;
GdkPixbuf * pixbuf; GdkPixbuf * pixbuf;
gchar * name; gchar * name;
gchar * uri; GFile * location;
GFile * file;
NameIcon * item; NameIcon * item;
model = GTK_TREE_MODEL (obj->priv->bookmarks_store); model = GTK_TREE_MODEL (obj->priv->bookmarks_store);
uri = xed_file_bookmarks_store_get_uri (obj->priv-> location = xed_file_bookmarks_store_get_location (obj->priv->
bookmarks_store, bookmarks_store,
iter); iter);
if (uri == NULL) if (location == NULL)
return; return;
file = g_file_new_for_uri (uri);
g_free (uri);
gtk_tree_model_get (model, iter, gtk_tree_model_get (model, iter,
XED_FILE_BOOKMARKS_STORE_COLUMN_ICON, XED_FILE_BOOKMARKS_STORE_COLUMN_ICON,
&pixbuf, &pixbuf,
@ -1087,7 +1083,7 @@ add_bookmark_hash (XedFileBrowserWidget * obj,
item->icon = pixbuf; item->icon = pixbuf;
g_hash_table_insert (obj->priv->bookmarks_hash, g_hash_table_insert (obj->priv->bookmarks_hash,
file, location,
item); item);
} }
@ -1581,8 +1577,6 @@ jump_to_location (XedFileBrowserWidget * obj, GList * item,
GList *(*iter_func) (GList *); GList *(*iter_func) (GList *);
GtkWidget *menu_from; GtkWidget *menu_from;
GtkWidget *menu_to; GtkWidget *menu_to;
gchar *root;
gchar *virtual_root;
if (!obj->priv->locations) if (!obj->priv->locations)
return; return;
@ -1643,15 +1637,9 @@ jump_to_location (XedFileBrowserWidget * obj, GList * item,
loc = (Location *) (obj->priv->current_location->data); loc = (Location *) (obj->priv->current_location->data);
/* Set the new root + virtual root */ /* Set the new root + virtual root */
root = g_file_get_uri (loc->root);
virtual_root = g_file_get_uri (loc->virtual_root);
xed_file_browser_widget_set_root_and_virtual_root (obj, xed_file_browser_widget_set_root_and_virtual_root (obj,
root, loc->root,
virtual_root); loc->virtual_root);
g_free (root);
g_free (virtual_root);
obj->priv->changing_location = FALSE; obj->priv->changing_location = FALSE;
} }
@ -1840,8 +1828,8 @@ xed_file_browser_widget_show_files (XedFileBrowserWidget * obj)
void void
xed_file_browser_widget_set_root_and_virtual_root (XedFileBrowserWidget *obj, xed_file_browser_widget_set_root_and_virtual_root (XedFileBrowserWidget *obj,
gchar const *root, GFile *root,
gchar const *virtual_root) GFile *virtual_root)
{ {
XedFileBrowserStoreResult result; XedFileBrowserStoreResult result;
@ -1860,12 +1848,10 @@ xed_file_browser_widget_set_root_and_virtual_root (XedFileBrowserWidget *obj,
void void
xed_file_browser_widget_set_root (XedFileBrowserWidget * obj, xed_file_browser_widget_set_root (XedFileBrowserWidget * obj,
gchar const *root, GFile *root,
gboolean virtual_root) gboolean virtual_root)
{ {
GFile *file;
GFile *parent; GFile *parent;
gchar *str;
if (!virtual_root) { if (!virtual_root) {
xed_file_browser_widget_set_root_and_virtual_root (obj, xed_file_browser_widget_set_root_and_virtual_root (obj,
@ -1877,16 +1863,11 @@ xed_file_browser_widget_set_root (XedFileBrowserWidget * obj,
if (!root) if (!root)
return; return;
file = g_file_new_for_uri (root); parent = get_topmost_file (root);
parent = get_topmost_file (file);
str = g_file_get_uri (parent);
xed_file_browser_widget_set_root_and_virtual_root xed_file_browser_widget_set_root_and_virtual_root
(obj, str, root); (obj, parent, root);
g_free (str);
g_object_unref (file);
g_object_unref (parent); g_object_unref (parent);
} }
@ -2113,7 +2094,6 @@ activate_mount (XedFileBrowserWidget *widget,
GMount *mount) GMount *mount)
{ {
GFile *root; GFile *root;
gchar *uri;
if (!mount) if (!mount)
{ {
@ -2135,11 +2115,9 @@ activate_mount (XedFileBrowserWidget *widget,
} }
root = g_mount_get_root (mount); root = g_mount_get_root (mount);
uri = g_file_get_uri (root);
xed_file_browser_widget_set_root (widget, uri, FALSE); xed_file_browser_widget_set_root (widget, root, FALSE);
g_free (uri);
g_object_unref (root); g_object_unref (root);
} }
@ -2370,7 +2348,7 @@ bookmark_open (XedFileBrowserWidget *obj,
GtkTreeModel *model, GtkTreeModel *model,
GtkTreeIter *iter) GtkTreeIter *iter)
{ {
gchar *uri; GFile *location;
gint flags; gint flags;
gtk_tree_model_get (model, iter, gtk_tree_model_get (model, iter,
@ -2392,11 +2370,11 @@ bookmark_open (XedFileBrowserWidget *obj,
return; return;
} }
uri = location =
xed_file_bookmarks_store_get_uri xed_file_bookmarks_store_get_location
(XED_FILE_BOOKMARKS_STORE (model), iter); (XED_FILE_BOOKMARKS_STORE (model), iter);
if (uri) { if (location) {
/* here we check if the bookmark is a mount point, or if it /* here we check if the bookmark is a mount point, or if it
is a remote bookmark. If that's the case, we will set the is a remote bookmark. If that's the case, we will set the
root to the uri of the bookmark and not try to set the root to the uri of the bookmark and not try to set the
@ -2405,18 +2383,18 @@ bookmark_open (XedFileBrowserWidget *obj,
if ((flags & XED_FILE_BOOKMARKS_STORE_IS_MOUNT) || if ((flags & XED_FILE_BOOKMARKS_STORE_IS_MOUNT) ||
(flags & XED_FILE_BOOKMARKS_STORE_IS_REMOTE_BOOKMARK)) { (flags & XED_FILE_BOOKMARKS_STORE_IS_REMOTE_BOOKMARK)) {
xed_file_browser_widget_set_root (obj, xed_file_browser_widget_set_root (obj,
uri, location,
FALSE); FALSE);
} else { } else {
xed_file_browser_widget_set_root (obj, xed_file_browser_widget_set_root (obj,
uri, location,
TRUE); TRUE);
} }
g_object_unref (location);
} else { } else {
g_warning ("No uri!"); g_warning ("No uri!");
} }
g_free (uri);
} }
static void static void
@ -2424,19 +2402,17 @@ file_open (XedFileBrowserWidget *obj,
GtkTreeModel *model, GtkTreeModel *model,
GtkTreeIter *iter) GtkTreeIter *iter)
{ {
gchar *uri; GFile *location;
gint flags; gint flags;
gtk_tree_model_get (model, iter, gtk_tree_model_get (model, iter,
XED_FILE_BROWSER_STORE_COLUMN_FLAGS, &flags, XED_FILE_BROWSER_STORE_COLUMN_FLAGS, &flags,
XED_FILE_BROWSER_STORE_COLUMN_URI, &uri, XED_FILE_BROWSER_STORE_COLUMN_LOCATION, &location,
-1); -1);
if (!FILE_IS_DIR (flags) && !FILE_IS_DUMMY (flags)) { if (!FILE_IS_DIR (flags) && !FILE_IS_DUMMY (flags)) {
g_signal_emit (obj, signals[URI_ACTIVATED], 0, uri); g_signal_emit (obj, signals[LOCATION_ACTIVATED], 0, location);
} }
g_free (uri);
} }
static gboolean static gboolean
@ -2446,17 +2422,20 @@ directory_open (XedFileBrowserWidget *obj,
{ {
gboolean result = FALSE; gboolean result = FALSE;
GError *error = NULL; GError *error = NULL;
gchar *uri = NULL; GFile *location;
XedFileBrowserStoreFlag flags; XedFileBrowserStoreFlag flags;
gtk_tree_model_get (model, iter, gtk_tree_model_get (model, iter,
XED_FILE_BROWSER_STORE_COLUMN_FLAGS, &flags, XED_FILE_BROWSER_STORE_COLUMN_FLAGS, &flags,
XED_FILE_BROWSER_STORE_COLUMN_URI, &uri, XED_FILE_BROWSER_STORE_COLUMN_LOCATION, &location,
-1); -1);
if (FILE_IS_DIR (flags)) { if (FILE_IS_DIR (flags) && location) {
gchar *uri;
result = TRUE; result = TRUE;
uri = g_file_get_uri (location);
if (!gtk_show_uri (gtk_widget_get_screen (GTK_WIDGET (obj)), uri, GDK_CURRENT_TIME, &error)) { if (!gtk_show_uri (gtk_widget_get_screen (GTK_WIDGET (obj)), uri, GDK_CURRENT_TIME, &error)) {
g_signal_emit (obj, signals[ERROR], 0, g_signal_emit (obj, signals[ERROR], 0,
XED_FILE_BROWSER_ERROR_OPEN_DIRECTORY, XED_FILE_BROWSER_ERROR_OPEN_DIRECTORY,
@ -2465,9 +2444,9 @@ directory_open (XedFileBrowserWidget *obj,
g_error_free (error); g_error_free (error);
error = NULL; error = NULL;
} }
}
g_free (uri); g_free (uri);
}
return result; return result;
} }
@ -2514,8 +2493,7 @@ on_virtual_root_changed (XedFileBrowserStore * model,
XedFileBrowserWidget * obj) XedFileBrowserWidget * obj)
{ {
GtkTreeIter iter; GtkTreeIter iter;
gchar *uri; GFile *location;
gchar *root_uri;
GtkTreeIter root; GtkTreeIter root;
GtkAction *action; GtkAction *action;
Location *loc; Location *loc;
@ -2529,8 +2507,8 @@ on_virtual_root_changed (XedFileBrowserStore * model,
if (xed_file_browser_store_get_iter_virtual_root (model, &iter)) { if (xed_file_browser_store_get_iter_virtual_root (model, &iter)) {
gtk_tree_model_get (GTK_TREE_MODEL (model), &iter, gtk_tree_model_get (GTK_TREE_MODEL (model), &iter,
XED_FILE_BROWSER_STORE_COLUMN_URI, XED_FILE_BROWSER_STORE_COLUMN_LOCATION,
&uri, -1); &location, -1);
if (xed_file_browser_store_get_iter_root (model, &root)) { if (xed_file_browser_store_get_iter_root (model, &root)) {
if (!obj->priv->changing_location) { if (!obj->priv->changing_location) {
@ -2538,14 +2516,9 @@ on_virtual_root_changed (XedFileBrowserStore * model,
if (obj->priv->current_location) if (obj->priv->current_location)
clear_next_locations (obj); clear_next_locations (obj);
root_uri =
xed_file_browser_store_get_root
(model);
loc = g_new (Location, 1); loc = g_new (Location, 1);
loc->root = g_file_new_for_uri (root_uri); loc->root = xed_file_browser_store_get_root (model);
loc->virtual_root = g_file_new_for_uri (uri); loc->virtual_root = g_object_ref (location);
g_free (root_uri);
if (obj->priv->current_location) { if (obj->priv->current_location) {
/* Add current location to the menu so we can go back /* Add current location to the menu so we can go back
@ -2614,7 +2587,6 @@ on_virtual_root_changed (XedFileBrowserStore * model,
} }
check_current_item (obj, TRUE); check_current_item (obj, TRUE);
g_free (uri);
} else { } else {
g_message ("NO!"); g_message ("NO!");
} }
@ -2694,7 +2666,6 @@ on_combo_changed (GtkComboBox * combo, XedFileBrowserWidget * obj)
{ {
GtkTreeIter iter; GtkTreeIter iter;
guint id; guint id;
gchar * uri;
GFile * file; GFile * file;
if (!gtk_combo_box_get_active_iter (combo, &iter)) if (!gtk_combo_box_get_active_iter (combo, &iter))
@ -2713,11 +2684,8 @@ on_combo_changed (GtkComboBox * combo, XedFileBrowserWidget * obj)
(obj->priv->combo_model), &iter, (obj->priv->combo_model), &iter,
COLUMN_FILE, &file, -1); COLUMN_FILE, &file, -1);
uri = g_file_get_uri (file); xed_file_browser_store_set_virtual_root_from_location (obj->priv->file_store, file);
xed_file_browser_store_set_virtual_root_from_string
(obj->priv->file_store, uri);
g_free (uri);
g_object_unref (file); g_object_unref (file);
break; break;
} }
@ -2902,22 +2870,19 @@ on_bookmarks_row_deleted (GtkTreeModel * model,
XedFileBrowserWidget *obj) XedFileBrowserWidget *obj)
{ {
GtkTreeIter iter; GtkTreeIter iter;
gchar * uri; GFile *location;
GFile * file;
if (!gtk_tree_model_get_iter (model, &iter, path)) if (!gtk_tree_model_get_iter (model, &iter, path))
return; return;
uri = xed_file_bookmarks_store_get_uri (obj->priv->bookmarks_store, &iter); location = xed_file_bookmarks_store_get_location (obj->priv->bookmarks_store, &iter);
if (!uri) if (!location)
return; return;
file = g_file_new_for_uri (uri); g_hash_table_remove (obj->priv->bookmarks_hash, location);
g_hash_table_remove (obj->priv->bookmarks_hash, file);
g_object_unref (file); g_object_unref (location);
g_free (uri);
} }
static void static void

View File

@ -58,8 +58,8 @@ struct _XedFileBrowserWidgetClass
GtkBoxClass parent_class; GtkBoxClass parent_class;
/* Signals */ /* Signals */
void (*uri_activated) (XedFileBrowserWidget * widget, void (*location_activated) (XedFileBrowserWidget * widget,
gchar const *uri); GFile *location);
void (*error) (XedFileBrowserWidget * widget, void (*error) (XedFileBrowserWidget * widget,
guint code, guint code,
gchar const *message); gchar const *message);
@ -79,12 +79,12 @@ void xed_file_browser_widget_show_bookmarks (XedFileBrowserWidget * obj);
void xed_file_browser_widget_show_files (XedFileBrowserWidget * obj); void xed_file_browser_widget_show_files (XedFileBrowserWidget * obj);
void xed_file_browser_widget_set_root (XedFileBrowserWidget * obj, void xed_file_browser_widget_set_root (XedFileBrowserWidget * obj,
gchar const *root, GFile *root,
gboolean virtual_root); gboolean virtual_root);
void void
xed_file_browser_widget_set_root_and_virtual_root (XedFileBrowserWidget * obj, xed_file_browser_widget_set_root_and_virtual_root (XedFileBrowserWidget * obj,
gchar const *root, GFile *root,
gchar const *virtual_root); GFile *virtual_root);
gboolean gboolean
xed_file_browser_widget_get_selected_directory (XedFileBrowserWidget * obj, xed_file_browser_widget_get_selected_directory (XedFileBrowserWidget * obj,

View File

@ -20,7 +20,7 @@
* Boston, MA 02110-1301 USA * Boston, MA 02110-1301 USA
*/ */
#include "xed-gio-document-loader.h" #include "xed-document-loader.h"
#include "xed-prefs-manager-app.h" #include "xed-prefs-manager-app.h"
#include <gio/gio.h> #include <gio/gio.h>
#include <gtk/gtk.h> #include <gtk/gtk.h>

View File

@ -20,7 +20,7 @@
* Boston, MA 02110-1301 USA * Boston, MA 02110-1301 USA
*/ */
#include "xed-gio-document-loader.h" #include "xed-document-loader.h"
#include "xed-prefs-manager-app.h" #include "xed-prefs-manager-app.h"
#include <gio/gio.h> #include <gio/gio.h>
#include <gtk/gtk.h> #include <gtk/gtk.h>

View File

@ -51,8 +51,6 @@ NOINST_H_FILES = \
xed-document-output-stream.h \ xed-document-output-stream.h \
xed-document-saver.h \ xed-document-saver.h \
xed-documents-panel.h \ xed-documents-panel.h \
xed-gio-document-loader.h \
xed-gio-document-saver.h \
xed-history-entry.h \ xed-history-entry.h \
xed-io-error-message-area.h \ xed-io-error-message-area.h \
xed-language-manager.h \ xed-language-manager.h \
@ -123,9 +121,7 @@ libxed_c_files = \
xed-document-input-stream.c \ xed-document-input-stream.c \
xed-document-loader.c \ xed-document-loader.c \
xed-document-output-stream.c \ xed-document-output-stream.c \
xed-gio-document-loader.c \
xed-document-saver.c \ xed-document-saver.c \
xed-gio-document-saver.c \
xed-documents-panel.c \ xed-documents-panel.c \
xed-encodings.c \ xed-encodings.c \
xed-encodings-combo-box.c \ xed-encodings-combo-box.c \

View File

@ -124,7 +124,7 @@ is_duplicated_file (GSList *files,
/* File loading */ /* File loading */
static gint static gint
load_file_list (XedWindow *window, load_file_list (XedWindow *window,
GSList *files, const GSList *files,
const XedEncoding *encoding, const XedEncoding *encoding,
gint line_pos, gint line_pos,
gboolean create) gboolean create)
@ -134,7 +134,7 @@ load_file_list (XedWindow *window,
gboolean jump_to = TRUE; /* Whether to jump to the new tab */ gboolean jump_to = TRUE; /* Whether to jump to the new tab */
GList *win_docs; GList *win_docs;
GSList *files_to_load = NULL; GSList *files_to_load = NULL;
GSList *l; const GSList *l;
xed_debug (DEBUG_COMMANDS); xed_debug (DEBUG_COMMANDS);
@ -197,12 +197,7 @@ load_file_list (XedWindow *window,
if (xed_document_is_untouched (doc) && (xed_tab_get_state (tab) == XED_TAB_STATE_NORMAL)) if (xed_document_is_untouched (doc) && (xed_tab_get_state (tab) == XED_TAB_STATE_NORMAL))
{ {
gchar *uri; _xed_tab_load (tab, l->data, encoding, line_pos, create);
// FIXME: pass the GFile to tab when api is there
uri = g_file_get_uri (l->data);
_xed_tab_load (tab, uri, encoding, line_pos, create);
g_free (uri);
l = g_slist_next (l); l = g_slist_next (l);
jump_to = FALSE; jump_to = FALSE;
@ -213,14 +208,9 @@ load_file_list (XedWindow *window,
while (l != NULL) while (l != NULL)
{ {
gchar *uri;
g_return_val_if_fail (l->data != NULL, 0); g_return_val_if_fail (l->data != NULL, 0);
// FIXME: pass the GFile to tab when api is there tab = xed_window_create_tab_from_location (window, l->data, encoding, line_pos, create, jump_to);
uri = g_file_get_uri (l->data);
tab = xed_window_create_tab_from_uri (window, uri, encoding, line_pos, create, jump_to);
g_free (uri);
if (tab != NULL) if (tab != NULL)
{ {
@ -264,114 +254,62 @@ load_file_list (XedWindow *window,
return loaded_files; return loaded_files;
} }
// FIXME: we should expose API with GFile and just make the uri
// variants backward compat wrappers
static gint
load_uri_list (XedWindow *window,
const GSList *uris,
const XedEncoding *encoding,
gint line_pos,
gboolean create)
{
GSList *files = NULL;
const GSList *u;
gint ret;
for (u = uris; u != NULL; u = u->next)
{
gchar *uri = u->data;
if (xed_utils_is_valid_uri (uri))
{
files = g_slist_prepend (files, g_file_new_for_uri (uri));
}
else
{
g_warning ("invalid uri: %s", uri);
}
}
files = g_slist_reverse (files);
ret = load_file_list (window, files, encoding, line_pos, create);
g_slist_foreach (files, (GFunc) g_object_unref, NULL);
g_slist_free (files);
return ret;
}
/** /**
* xed_commands_load_uri: * xed_commands_load_location:
* @window: * @window:
* @uri: * @uri:
* @encoding: (allow-none): * @encoding: (allow-none):
* @line_pos: * @line_pos:
* *
* Do nothing if uri does not exist * Do nothing if location does not exist
*/ */
void void
xed_commands_load_uri (XedWindow *window, xed_commands_load_location (XedWindow *window,
const gchar *uri, GFile *location,
const XedEncoding *encoding, const XedEncoding *encoding,
gint line_pos) gint line_pos)
{ {
GSList *uris = NULL; GSList *locations = NULL;
gchar *uri;
g_return_if_fail (XED_IS_WINDOW (window)); g_return_if_fail (XED_IS_WINDOW (window));
g_return_if_fail (uri != NULL); g_return_if_fail (G_IS_FILE (location));
g_return_if_fail (xed_utils_is_valid_uri (uri)); g_return_if_fail (xed_utils_is_valid_location (location));
uri = g_file_get_uri (location);
xed_debug_message (DEBUG_COMMANDS, "Loading URI '%s'", uri); xed_debug_message (DEBUG_COMMANDS, "Loading URI '%s'", uri);
g_free (uri);
uris = g_slist_prepend (uris, (gchar *)uri); locations = g_slist_prepend (locations, location);
load_uri_list (window, uris, encoding, line_pos, FALSE); load_file_list (window, locations, encoding, line_pos, FALSE);
g_slist_free (uris); g_slist_free (locations);
} }
/** /**
* xed_commands_load_uris: * xed_commands_load_locations:
* @window: * @window:
* @uris: * @uris:
* @encoding: * @encoding:
* @line_pos: * @line_pos:
* *
* Ignore non-existing URIs * Ignore non-existing locations
* *
* Returns: * Returns:
*/ */
gint gint
xed_commands_load_uris (XedWindow *window, xed_commands_load_locations (XedWindow *window,
const GSList *uris, const GSList *locations,
const XedEncoding *encoding, const XedEncoding *encoding,
gint line_pos) gint line_pos)
{ {
g_return_val_if_fail (XED_IS_WINDOW (window), 0); g_return_val_if_fail (XED_IS_WINDOW (window), 0);
g_return_val_if_fail ((uris != NULL) && (uris->data != NULL), 0); g_return_val_if_fail ((locations != NULL) && (locations->data != NULL), 0);
xed_debug (DEBUG_COMMANDS); xed_debug (DEBUG_COMMANDS);
return load_uri_list (window, uris, encoding, line_pos, FALSE); return load_file_list (window, locations, encoding, line_pos, FALSE);
}
/*
* This should become public once we convert all api to GFile:
*/
static gint
xed_commands_load_files (XedWindow *window,
GSList *files,
const XedEncoding *encoding,
gint line_pos)
{
g_return_val_if_fail (XED_IS_WINDOW (window), 0);
g_return_val_if_fail ((files != NULL) && (files->data != NULL), 0);
xed_debug (DEBUG_COMMANDS);
return load_file_list (window, files, encoding, line_pos, FALSE);
} }
/* /*
@ -426,7 +364,7 @@ open_dialog_response_cb (XedFileChooserDialog *dialog,
/* Remember the folder we navigated to */ /* Remember the folder we navigated to */
_xed_window_set_default_location (window, files->data); _xed_window_set_default_location (window, files->data);
xed_commands_load_files (window, files, encoding, 0); xed_commands_load_locations (window, files, encoding, 0);
g_slist_foreach (files, (GFunc) g_object_unref, NULL); g_slist_foreach (files, (GFunc) g_object_unref, NULL);
g_slist_free (files); g_slist_free (files);
@ -616,7 +554,6 @@ save_dialog_response_cb (XedFileChooserDialog *dialog,
{ {
XedDocument *doc; XedDocument *doc;
gchar *parse_name; gchar *parse_name;
gchar *uri;
doc = xed_tab_get_document (tab); doc = xed_tab_get_document (tab);
g_return_if_fail (XED_IS_DOCUMENT (doc)); g_return_if_fail (XED_IS_DOCUMENT (doc));
@ -634,10 +571,7 @@ save_dialog_response_cb (XedFileChooserDialog *dialog,
* even if the saving fails... */ * even if the saving fails... */
_xed_window_set_default_location (window, file); _xed_window_set_default_location (window, file);
// FIXME: pass the GFile to tab when api is there _xed_tab_save_as (tab, file, encoding, newline_type);
uri = g_file_get_uri (file);
_xed_tab_save_as (tab, uri, encoding, newline_type);
g_free (uri);
} }
g_object_unref (file); g_object_unref (file);

View File

@ -7,10 +7,10 @@
G_BEGIN_DECLS G_BEGIN_DECLS
/* Do nothing if URI does not exist */ /* Do nothing if URI does not exist */
void xed_commands_load_uri (XedWindow *window, const gchar *uri, const XedEncoding *encoding, gint line_pos); void xed_commands_load_location (XedWindow *window, GFile *location, const XedEncoding *encoding, gint line_pos);
/* Ignore non-existing URIs */ /* Ignore non-existing URIs */
gint xed_commands_load_uris (XedWindow *window, const GSList *uris, const XedEncoding *encoding, gint line_pos); gint xed_commands_load_locations (XedWindow *window, const GSList *locations, const XedEncoding *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_all_documents (XedWindow *window); void xed_commands_save_all_documents (XedWindow *window);

View File

@ -34,39 +34,91 @@
#endif #endif
#include <glib/gi18n.h> #include <glib/gi18n.h>
#include <glib/gstdio.h>
#include <gio/gio.h>
#include "xed-document-loader.h" #include "xed-document-loader.h"
#include "xed-document-output-stream.h"
#include "xed-smart-charset-converter.h"
#include "xed-prefs-manager.h"
#include "xed-debug.h" #include "xed-debug.h"
#include "xed-metadata-manager.h" #include "xed-metadata-manager.h"
#include "xed-utils.h" #include "xed-utils.h"
#include "xed-marshal.h" #include "xed-marshal.h"
#include "xed-enum-types.h" #include "xed-enum-types.h"
/* Those are for the the xed_document_loader_new() factory */ #ifndef ENABLE_GVFS_METADATA
#include "xed-gio-document-loader.h" #include "xed_metadata-manager.h"
#endif
G_DEFINE_ABSTRACT_TYPE(XedDocumentLoader, xed_document_loader, G_TYPE_OBJECT) typedef struct
{
XedDocumentLoader *loader;
GCancellable *cancellable;
/* Signals */ gssize read;
gboolean tried_mount;
}AsyncData;
enum { enum
{
LOADING, LOADING,
LAST_SIGNAL LAST_SIGNAL
}; };
static guint signals[LAST_SIGNAL] = { 0 }; static guint signals[LAST_SIGNAL] = { 0 };
/* Properties */
enum enum
{ {
PROP_0, PROP_0,
PROP_DOCUMENT, PROP_DOCUMENT,
PROP_URI, PROP_LOCATION,
PROP_ENCODING, PROP_ENCODING,
PROP_NEWLINE_TYPE PROP_NEWLINE_TYPE
}; };
#define READ_CHUNK_SIZE 8192
#define REMOTE_QUERY_ATTRIBUTES G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE "," \
G_FILE_ATTRIBUTE_STANDARD_TYPE "," \
G_FILE_ATTRIBUTE_TIME_MODIFIED "," \
G_FILE_ATTRIBUTE_STANDARD_SIZE "," \
G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE "," \
XED_METADATA_ATTRIBUTE_ENCODING
#define XED_DOCUMENT_LOADER_GET_PRIVATE(object) \
(G_TYPE_INSTANCE_GET_PRIVATE ((object), \
XED_TYPE_DOCUMENT_LOADER, \
XedDocumentLoaderPrivate))
static void open_async_read (AsyncData *async);
struct _XedDocumentLoaderPrivate
{
XedDocument *document;
gboolean used;
/* Info on the current file */
GFileInfo *info;
GFile *location;
const XedEncoding *encoding;
const XedEncoding *auto_detected_encoding;
XedDocumentNewlineType auto_detected_newline_type;
goffset bytes_read;
/* Handle for remote files */
GCancellable *cancellable;
GInputStream *stream;
GOutputStream *output;
XedSmartCharsetConverter *converter;
gchar buffer[READ_CHUNK_SIZE];
GError *error;
};
G_DEFINE_TYPE(XedDocumentLoader, xed_document_loader, G_TYPE_OBJECT)
static void static void
xed_document_loader_set_property (GObject *object, xed_document_loader_set_property (GObject *object,
guint prop_id, guint prop_id,
@ -78,19 +130,19 @@ xed_document_loader_set_property (GObject *object,
switch (prop_id) switch (prop_id)
{ {
case PROP_DOCUMENT: case PROP_DOCUMENT:
g_return_if_fail (loader->document == NULL); g_return_if_fail (loader->priv->document == NULL);
loader->document = g_value_get_object (value); loader->priv->document = g_value_get_object (value);
break; break;
case PROP_URI: case PROP_LOCATION:
g_return_if_fail (loader->uri == NULL); g_return_if_fail (loader->priv->location == NULL);
loader->uri = g_value_dup_string (value); loader->priv->location = g_value_dup_object (value);
break; break;
case PROP_ENCODING: case PROP_ENCODING:
g_return_if_fail (loader->encoding == NULL); g_return_if_fail (loader->priv->encoding == NULL);
loader->encoding = g_value_get_boxed (value); loader->priv->encoding = g_value_get_boxed (value);
break; break;
case PROP_NEWLINE_TYPE: case PROP_NEWLINE_TYPE:
loader->auto_detected_newline_type = g_value_get_enum (value); loader->priv->auto_detected_newline_type = g_value_get_enum (value);
break; break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@ -109,16 +161,16 @@ xed_document_loader_get_property (GObject *object,
switch (prop_id) switch (prop_id)
{ {
case PROP_DOCUMENT: case PROP_DOCUMENT:
g_value_set_object (value, loader->document); g_value_set_object (value, loader->priv->document);
break; break;
case PROP_URI: case PROP_LOCATION:
g_value_set_string (value, loader->uri); g_value_set_object (value, loader->priv->location);
break; break;
case PROP_ENCODING: case PROP_ENCODING:
g_value_set_boxed (value, xed_document_loader_get_encoding (loader)); g_value_set_boxed (value, xed_document_loader_get_encoding (loader));
break; break;
case PROP_NEWLINE_TYPE: case PROP_NEWLINE_TYPE:
g_value_set_enum (value, loader->auto_detected_newline_type); g_value_set_enum (value, loader->priv->auto_detected_newline_type);
break; break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@ -126,28 +178,54 @@ xed_document_loader_get_property (GObject *object,
} }
} }
static void
xed_document_loader_finalize (GObject *object)
{
XedDocumentLoader *loader = XED_DOCUMENT_LOADER (object);
g_free (loader->uri);
if (loader->info)
g_object_unref (loader->info);
G_OBJECT_CLASS (xed_document_loader_parent_class)->finalize (object);
}
static void static void
xed_document_loader_dispose (GObject *object) xed_document_loader_dispose (GObject *object)
{ {
XedDocumentLoader *loader = XED_DOCUMENT_LOADER (object); XedDocumentLoaderPrivate *priv;
if (loader->info != NULL) priv = XED_DOCUMENT_LOADER (object)->priv;
if (priv->cancellable != NULL)
{ {
g_object_unref (loader->info); g_cancellable_cancel (priv->cancellable);
loader->info = NULL; g_object_unref (priv->cancellable);
priv->cancellable = NULL;
}
if (priv->stream != NULL)
{
g_object_unref (priv->stream);
priv->stream = NULL;
}
if (priv->output != NULL)
{
g_object_unref (priv->output);
priv->output = NULL;
}
if (priv->converter != NULL)
{
g_object_unref (priv->converter);
priv->converter = NULL;
}
if (priv->error != NULL)
{
g_error_free (priv->error);
priv->error = NULL;
}
if (priv->info != NULL)
{
g_object_unref (priv->info);
priv->info = NULL;
}
if (priv->location != NULL)
{
g_object_unref (priv->location);
priv->location = NULL;
} }
G_OBJECT_CLASS (xed_document_loader_parent_class)->dispose (object); G_OBJECT_CLASS (xed_document_loader_parent_class)->dispose (object);
@ -158,7 +236,6 @@ xed_document_loader_class_init (XedDocumentLoaderClass *klass)
{ {
GObjectClass *object_class = G_OBJECT_CLASS (klass); GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = xed_document_loader_finalize;
object_class->dispose = xed_document_loader_dispose; object_class->dispose = xed_document_loader_dispose;
object_class->get_property = xed_document_loader_get_property; object_class->get_property = xed_document_loader_get_property;
object_class->set_property = xed_document_loader_set_property; object_class->set_property = xed_document_loader_set_property;
@ -174,11 +251,11 @@ xed_document_loader_class_init (XedDocumentLoaderClass *klass)
G_PARAM_STATIC_STRINGS)); G_PARAM_STATIC_STRINGS));
g_object_class_install_property (object_class, g_object_class_install_property (object_class,
PROP_URI, PROP_LOCATION,
g_param_spec_string ("uri", g_param_spec_object ("location",
"URI", "LOCATION",
"The URI this XedDocumentLoader loads the document from", "The LOCATION this XedDocumentLoader loads the document from",
"", G_TYPE_FILE,
G_PARAM_READWRITE | G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY)); G_PARAM_CONSTRUCT_ONLY));
@ -192,7 +269,8 @@ xed_document_loader_class_init (XedDocumentLoaderClass *klass)
G_PARAM_CONSTRUCT_ONLY | G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS)); G_PARAM_STATIC_STRINGS));
g_object_class_install_property (object_class, PROP_NEWLINE_TYPE, g_object_class_install_property (object_class,
PROP_NEWLINE_TYPE,
g_param_spec_enum ("newline-type", g_param_spec_enum ("newline-type",
"Newline type", "Newline type",
"The accepted types of line ending", "The accepted types of line ending",
@ -202,8 +280,7 @@ xed_document_loader_class_init (XedDocumentLoaderClass *klass)
G_PARAM_STATIC_NAME | G_PARAM_STATIC_NAME |
G_PARAM_STATIC_BLURB)); G_PARAM_STATIC_BLURB));
signals[LOADING] = signals[LOADING] = g_signal_new ("loading",
g_signal_new ("loading",
G_OBJECT_CLASS_TYPE (object_class), G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_LAST, G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (XedDocumentLoaderClass, loading), G_STRUCT_OFFSET (XedDocumentLoaderClass, loading),
@ -213,13 +290,509 @@ xed_document_loader_class_init (XedDocumentLoaderClass *klass)
2, 2,
G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
G_TYPE_POINTER); G_TYPE_POINTER);
g_type_class_add_private (object_class, sizeof (XedDocumentLoaderPrivate));
} }
static void static void
xed_document_loader_init (XedDocumentLoader *loader) xed_document_loader_init (XedDocumentLoader *loader)
{ {
loader->used = FALSE; loader->priv = XED_DOCUMENT_LOADER_GET_PRIVATE (loader);
loader->auto_detected_newline_type = XED_DOCUMENT_NEWLINE_TYPE_DEFAULT;
loader->priv->used = FALSE;
loader->priv->auto_detected_newline_type = XED_DOCUMENT_NEWLINE_TYPE_DEFAULT;
loader->priv->converter = NULL;
loader->priv->error = NULL;
}
XedDocumentLoader *
xed_document_loader_new (XedDocument *doc,
GFile *location,
const XedEncoding *encoding)
{
g_return_val_if_fail (XED_IS_DOCUMENT (doc), NULL);
return XED_DOCUMENT_LOADER (g_object_new (XED_TYPE_DOCUMENT_LOADER,
"document", doc,
"location", location,
"encoding", encoding,
NULL));
}
static AsyncData *
async_data_new (XedDocumentLoader *loader)
{
AsyncData *async;
async = g_slice_new (AsyncData);
async->loader = loader;
async->cancellable = g_object_ref (loader->priv->cancellable);
async->tried_mount = FALSE;
return async;
}
static void
async_data_free (AsyncData *async)
{
g_object_unref (async->cancellable);
g_slice_free (AsyncData, async);
}
static const XedEncoding *
get_metadata_encoding (XedDocumentLoader *loader)
{
const XedEncoding *enc = NULL;
#ifndef ENABLE_GVFS_METADATA
gchar *charset;
GFile *location;
gchar *uri;
location = xed_document_loader_get_location (loader);
uri = g_file_get_uri (location);
g_object_unref (location);
charset = xed_metadata_manager_get (uri, "encoding");
g_free (uri);
if (charset == NULL)
{
return NULL;
}
enc = xed_encoding_get_from_charset (charset);
g_free (charset);
#else
GFileInfo *info;
info = xed_document_loader_get_info (loader);
/* check if encoding was set in the metadata */
if (g_file_info_has_attribute (info, XED_METADATA_ATTRIBUTE_ENCODING))
{
const gchar *charset;
charset = g_file_info_get_attribute_string (info, XED_METADATA_ATTRIBUTE_ENCODING);
if (charset == NULL)
{
return NULL;
}
enc = xed_encoding_get_from_charset (charset);
}
#endif
return enc;
}
static void
remote_load_completed_or_failed (XedDocumentLoader *loader,
AsyncData *async)
{
xed_document_loader_loading (loader, TRUE, loader->priv->error);
if (async)
{
async_data_free (async);
}
}
static void
async_failed (AsyncData *async,
GError *error)
{
g_propagate_error (&async->loader->priv->error, error);
remote_load_completed_or_failed (async->loader, async);
}
static void
close_input_stream_ready_cb (GInputStream *stream,
GAsyncResult *res,
AsyncData *async)
{
GError *error = NULL;
xed_debug (DEBUG_LOADER);
/* check cancelled state manually */
if (g_cancellable_is_cancelled (async->cancellable))
{
async_data_free (async);
return;
}
xed_debug_message (DEBUG_SAVER, "Finished closing input stream");
if (!g_input_stream_close_finish (stream, res, &error))
{
xed_debug_message (DEBUG_SAVER, "Closing input stream error: %s", error->message);
async_failed (async, error);
return;
}
xed_debug_message (DEBUG_SAVER, "Close output stream");
if (!g_output_stream_close (async->loader->priv->output, async->cancellable, &error))
{
async_failed (async, error);
return;
}
remote_load_completed_or_failed (async->loader, async);
}
static void
write_complete (AsyncData *async)
{
if (async->loader->priv->stream)
{
g_input_stream_close_async (G_INPUT_STREAM (async->loader->priv->stream),
G_PRIORITY_HIGH,
async->cancellable,
(GAsyncReadyCallback)close_input_stream_ready_cb,
async);
}
}
/* prototype, because they call each other... isn't C lovely */
static void read_file_chunk (AsyncData *async);
static void
write_file_chunk (AsyncData *async)
{
XedDocumentLoader *loader;
gssize bytes_written;
GError *error = NULL;
loader = async->loader;
/* we use sync methods on doc stream since it is in memory. Using async
would be racy and we can endup with invalidated iters */
bytes_written = g_output_stream_write (G_OUTPUT_STREAM (loader->priv->output),
loader->priv->buffer,
async->read,
async->cancellable,
&error);
xed_debug_message (DEBUG_SAVER, "Written: %" G_GSSIZE_FORMAT, bytes_written);
if (bytes_written == -1)
{
xed_debug_message (DEBUG_SAVER, "Write error: %s", error->message);
async_failed (async, error);
return;
}
/* note that this signal blocks the read... check if it isn't
* a performance problem
*/
xed_document_loader_loading (loader, FALSE, NULL);
read_file_chunk (async);
}
static void
async_read_cb (GInputStream *stream,
GAsyncResult *res,
AsyncData *async)
{
XedDocumentLoader *loader;
GError *error = NULL;
xed_debug (DEBUG_LOADER);
/* manually check cancelled state */
if (g_cancellable_is_cancelled (async->cancellable))
{
async_data_free (async);
return;
}
loader = async->loader;
async->read = g_input_stream_read_finish (stream, res, &error);
/* error occurred */
if (async->read == -1)
{
async_failed (async, error);
return;
}
/* Check for the extremely unlikely case where the file size overflows. */
if (loader->priv->bytes_read + async->read < loader->priv->bytes_read)
{
g_set_error (&loader->priv->error,
XED_DOCUMENT_ERROR,
XED_DOCUMENT_ERROR_TOO_BIG,
"File too big");
async_failed (async, loader->priv->error);
return;
}
/* Bump the size. */
loader->priv->bytes_read += async->read;
/* end of the file, we are done! */
if (async->read == 0)
{
loader->priv->auto_detected_encoding = xed_smart_charset_converter_get_guessed (loader->priv->converter);
loader->priv->auto_detected_newline_type =
xed_document_output_stream_detect_newline_type (XED_DOCUMENT_OUTPUT_STREAM (loader->priv->output));
/* Check if we needed some fallback char, if so, check if there was
a previous error and if not set a fallback used error */
/* FIXME Uncomment this when we want to manage conversion fallback */
/*if ((xed_smart_charset_converter_get_num_fallbacks (loader->priv->converter) != 0) &&
loader->priv->error == NULL)
{
g_set_error_literal (&loader->priv->error,
XED_DOCUMENT_ERROR,
XED_DOCUMENT_ERROR_CONVERSION_FALLBACK,
"There was a conversion error and it was "
"needed to use a fallback char");
}*/
write_complete (async);
return;
}
write_file_chunk (async);
}
static void
read_file_chunk (AsyncData *async)
{
XedDocumentLoader *loader;
loader = async->loader;
g_input_stream_read_async (G_INPUT_STREAM (loader->priv->stream),
loader->priv->buffer,
READ_CHUNK_SIZE,
G_PRIORITY_HIGH,
async->cancellable,
(GAsyncReadyCallback) async_read_cb,
async);
}
static GSList *
get_candidate_encodings (XedDocumentLoader *loader)
{
const XedEncoding *metadata;
GSList *encodings = NULL;
encodings = xed_prefs_manager_get_auto_detected_encodings ();
metadata = get_metadata_encoding (loader);
if (metadata != NULL)
{
encodings = g_slist_prepend (encodings, (gpointer)metadata);
}
return encodings;
}
static void
finish_query_info (AsyncData *async)
{
XedDocumentLoader *loader;
GInputStream *conv_stream;
GFileInfo *info;
GSList *candidate_encodings;
loader = async->loader;
info = loader->priv->info;
/* if it's not a regular file, error out... */
if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_TYPE) &&
g_file_info_get_file_type (info) != G_FILE_TYPE_REGULAR)
{
g_set_error (&loader->priv->error,
G_IO_ERROR,
G_IO_ERROR_NOT_REGULAR_FILE,
"Not a regular file");
remote_load_completed_or_failed (loader, async);
return;
}
/* Get the candidate encodings */
if (loader->priv->encoding == NULL)
{
candidate_encodings = get_candidate_encodings (loader);
}
else
{
candidate_encodings = g_slist_prepend (NULL, (gpointer) loader->priv->encoding);
}
loader->priv->converter = xed_smart_charset_converter_new (candidate_encodings);
g_slist_free (candidate_encodings);
conv_stream = g_converter_input_stream_new (loader->priv->stream, G_CONVERTER (loader->priv->converter));
g_object_unref (loader->priv->stream);
loader->priv->stream = conv_stream;
/* Output stream */
loader->priv->output = xed_document_output_stream_new (loader->priv->document);
/* start reading */
read_file_chunk (async);
}
static void
query_info_cb (GFile *source,
GAsyncResult *res,
AsyncData *async)
{
GFileInfo *info;
GError *error = NULL;
xed_debug (DEBUG_LOADER);
/* manually check the cancelled state */
if (g_cancellable_is_cancelled (async->cancellable))
{
async_data_free (async);
return;
}
/* finish the info query */
info = g_file_query_info_finish (async->loader->priv->location, res, &error);
if (info == NULL)
{
/* propagate the error and clean up */
async_failed (async, error);
return;
}
async->loader->priv->info = info;
finish_query_info (async);
}
static void
mount_ready_callback (GFile *file,
GAsyncResult *res,
AsyncData *async)
{
GError *error = NULL;
gboolean mounted;
xed_debug (DEBUG_LOADER);
/* manual check for cancelled state */
if (g_cancellable_is_cancelled (async->cancellable))
{
async_data_free (async);
return;
}
mounted = g_file_mount_enclosing_volume_finish (file, res, &error);
if (!mounted)
{
async_failed (async, error);
}
else
{
/* try again to open the file for reading */
open_async_read (async);
}
}
static void
recover_not_mounted (AsyncData *async)
{
XedDocument *doc;
GMountOperation *mount_operation;
xed_debug (DEBUG_LOADER);
doc = xed_document_loader_get_document (async->loader);
mount_operation = _xed_document_create_mount_operation (doc);
async->tried_mount = TRUE;
g_file_mount_enclosing_volume (async->loader->priv->location,
G_MOUNT_MOUNT_NONE,
mount_operation,
async->cancellable,
(GAsyncReadyCallback) mount_ready_callback,
async);
g_object_unref (mount_operation);
}
static void
async_read_ready_callback (GObject *source,
GAsyncResult *res,
AsyncData *async)
{
GError *error = NULL;
XedDocumentLoader *loader;
xed_debug (DEBUG_LOADER);
/* manual check for cancelled state */
if (g_cancellable_is_cancelled (async->cancellable))
{
async_data_free (async);
return;
}
loader = async->loader;
loader->priv->stream = G_INPUT_STREAM (g_file_read_finish (loader->priv->location, res, &error));
if (!loader->priv->stream)
{
if (error->code == G_IO_ERROR_NOT_MOUNTED && !async->tried_mount)
{
recover_not_mounted (async);
g_error_free (error);
return;
}
/* Propagate error */
g_propagate_error (&loader->priv->error, error);
xed_document_loader_loading (loader, TRUE, loader->priv->error);
async_data_free (async);
return;
}
/* get the file info: note we cannot use
* g_file_input_stream_query_info_async since it is not able to get the
* content type etc, beside it is not supported by gvfs.
* Using the file instead of the stream is slightly racy, but for
* loading this is not too bad...
*/
g_file_query_info_async (loader->priv->location,
REMOTE_QUERY_ATTRIBUTES,
G_FILE_QUERY_INFO_NONE,
G_PRIORITY_HIGH,
async->cancellable,
(GAsyncReadyCallback) query_info_cb,
async);
}
static void
open_async_read (AsyncData *async)
{
g_file_read_async (async->loader->priv->location,
G_PRIORITY_HIGH,
async->cancellable,
(GAsyncReadyCallback) async_read_ready_callback,
async);
} }
void void
@ -240,54 +813,41 @@ xed_document_loader_loading (XedDocumentLoader *loader,
if (completed) if (completed)
{ {
if (error == NULL) if (error == NULL)
{
xed_debug_message (DEBUG_LOADER, "load completed"); xed_debug_message (DEBUG_LOADER, "load completed");
}
else else
{
xed_debug_message (DEBUG_LOADER, "load failed"); xed_debug_message (DEBUG_LOADER, "load failed");
}
g_object_unref (loader); g_object_unref (loader);
} }
} }
/* This is a factory method that returns an appopriate loader
* for the given uri.
*/
XedDocumentLoader *
xed_document_loader_new (XedDocument *doc,
const gchar *uri,
const XedEncoding *encoding)
{
XedDocumentLoader *loader;
GType loader_type;
g_return_val_if_fail (XED_IS_DOCUMENT (doc), NULL);
/* At the moment we just use gio loader in all cases...
* In the future it would be great to have a PolicyKit
* loader to get permission to save systen files etc */
loader_type = XED_TYPE_GIO_DOCUMENT_LOADER;
loader = XED_DOCUMENT_LOADER (g_object_new (loader_type,
"document", doc,
"uri", uri,
"encoding", encoding,
NULL));
return loader;
}
/* If enconding == NULL, the encoding will be autodetected */
void void
xed_document_loader_load (XedDocumentLoader *loader) xed_document_loader_load (XedDocumentLoader *loader)
{ {
AsyncData *async;
xed_debug (DEBUG_LOADER); xed_debug (DEBUG_LOADER);
g_return_if_fail (XED_IS_DOCUMENT_LOADER (loader)); g_return_if_fail (XED_IS_DOCUMENT_LOADER (loader));
/* the loader can be used just once, then it must be thrown away */ /* the loader can be used just once, then it must be thrown away */
g_return_if_fail (loader->used == FALSE); g_return_if_fail (loader->priv->used == FALSE);
loader->used = TRUE; loader->priv->used = TRUE;
XED_DOCUMENT_LOADER_GET_CLASS (loader)->load (loader); /* Make sure no load operation is currently running */
g_return_if_fail (loader->priv->cancellable == NULL);
/* loading start */
xed_document_loader_loading (loader, FALSE, NULL);
loader->priv->cancellable = g_cancellable_new ();
async = async_data_new (loader);
open_async_read (async);
} }
gboolean gboolean
@ -297,7 +857,21 @@ xed_document_loader_cancel (XedDocumentLoader *loader)
g_return_val_if_fail (XED_IS_DOCUMENT_LOADER (loader), FALSE); g_return_val_if_fail (XED_IS_DOCUMENT_LOADER (loader), FALSE);
return XED_DOCUMENT_LOADER_GET_CLASS (loader)->cancel (loader); if (loader->priv->cancellable == NULL)
{
return FALSE;
}
g_cancellable_cancel (loader->priv->cancellable);
g_set_error (&loader->priv->error,
G_IO_ERROR,
G_IO_ERROR_CANCELLED,
"Operation cancelled");
remote_load_completed_or_failed (loader, NULL);
return TRUE;
} }
XedDocument * XedDocument *
@ -305,16 +879,16 @@ xed_document_loader_get_document (XedDocumentLoader *loader)
{ {
g_return_val_if_fail (XED_IS_DOCUMENT_LOADER (loader), NULL); g_return_val_if_fail (XED_IS_DOCUMENT_LOADER (loader), NULL);
return loader->document; return loader->priv->document;
} }
/* Returns STDIN_URI if loading from stdin */ /* Returns STDIN_URI if loading from stdin */
const gchar * GFile *
xed_document_loader_get_uri (XedDocumentLoader *loader) xed_document_loader_get_location (XedDocumentLoader *loader)
{ {
g_return_val_if_fail (XED_IS_DOCUMENT_LOADER (loader), NULL); g_return_val_if_fail (XED_IS_DOCUMENT_LOADER (loader), NULL);
return loader->uri; return g_file_dup (loader->priv->location);
} }
goffset goffset
@ -322,7 +896,7 @@ xed_document_loader_get_bytes_read (XedDocumentLoader *loader)
{ {
g_return_val_if_fail (XED_IS_DOCUMENT_LOADER (loader), 0); g_return_val_if_fail (XED_IS_DOCUMENT_LOADER (loader), 0);
return XED_DOCUMENT_LOADER_GET_CLASS (loader)->get_bytes_read (loader); return loader->priv->bytes_read;
} }
const XedEncoding * const XedEncoding *
@ -330,22 +904,22 @@ xed_document_loader_get_encoding (XedDocumentLoader *loader)
{ {
g_return_val_if_fail (XED_IS_DOCUMENT_LOADER (loader), NULL); g_return_val_if_fail (XED_IS_DOCUMENT_LOADER (loader), NULL);
if (loader->encoding != NULL) if (loader->priv->encoding != NULL)
return loader->encoding; {
return loader->priv->encoding;
}
g_return_val_if_fail (loader->auto_detected_encoding != NULL, g_return_val_if_fail (loader->priv->auto_detected_encoding != NULL, xed_encoding_get_current ());
xed_encoding_get_current ());
return loader->auto_detected_encoding; return loader->priv->auto_detected_encoding;
} }
XedDocumentNewlineType XedDocumentNewlineType
xed_document_loader_get_newline_type (XedDocumentLoader *loader) xed_document_loader_get_newline_type (XedDocumentLoader *loader)
{ {
g_return_val_if_fail (XED_IS_DOCUMENT_LOADER (loader), g_return_val_if_fail (XED_IS_DOCUMENT_LOADER (loader), XED_DOCUMENT_NEWLINE_TYPE_LF);
XED_DOCUMENT_NEWLINE_TYPE_LF);
return loader->auto_detected_newline_type; return loader->priv->auto_detected_newline_type;
} }
GFileInfo * GFileInfo *
@ -353,5 +927,5 @@ xed_document_loader_get_info (XedDocumentLoader *loader)
{ {
g_return_val_if_fail (XED_IS_DOCUMENT_LOADER (loader), NULL); g_return_val_if_fail (XED_IS_DOCUMENT_LOADER (loader), NULL);
return loader->info; return loader->priv->info;
} }

View File

@ -36,9 +36,6 @@
G_BEGIN_DECLS G_BEGIN_DECLS
/*
* Type checking and casting macros
*/
#define XED_TYPE_DOCUMENT_LOADER (xed_document_loader_get_type()) #define XED_TYPE_DOCUMENT_LOADER (xed_document_loader_get_type())
#define XED_DOCUMENT_LOADER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), XED_TYPE_DOCUMENT_LOADER, XedDocumentLoader)) #define XED_DOCUMENT_LOADER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), XED_TYPE_DOCUMENT_LOADER, XedDocumentLoader))
#define XED_DOCUMENT_LOADER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), XED_TYPE_DOCUMENT_LOADER, XedDocumentLoaderClass)) #define XED_DOCUMENT_LOADER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), XED_TYPE_DOCUMENT_LOADER, XedDocumentLoaderClass))
@ -46,34 +43,17 @@ G_BEGIN_DECLS
#define XED_IS_DOCUMENT_LOADER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XED_TYPE_DOCUMENT_LOADER)) #define XED_IS_DOCUMENT_LOADER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XED_TYPE_DOCUMENT_LOADER))
#define XED_DOCUMENT_LOADER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), XED_TYPE_DOCUMENT_LOADER, XedDocumentLoaderClass)) #define XED_DOCUMENT_LOADER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), XED_TYPE_DOCUMENT_LOADER, XedDocumentLoaderClass))
/* Private structure type */
typedef struct _XedDocumentLoaderPrivate XedDocumentLoaderPrivate;
/*
* Main object structure
*/
typedef struct _XedDocumentLoader XedDocumentLoader; typedef struct _XedDocumentLoader XedDocumentLoader;
typedef struct _XedDocumentLoaderPrivate XedDocumentLoaderPrivate;
typedef struct _XedDocumentLoaderClass XedDocumentLoaderClass;
struct _XedDocumentLoader struct _XedDocumentLoader
{ {
GObject object; GObject object;
XedDocument *document; XedDocumentLoaderPrivate *priv;
gboolean used;
/* Info on the current file */
GFileInfo *info;
gchar *uri;
const XedEncoding *encoding;
const XedEncoding *auto_detected_encoding;
XedDocumentNewlineType auto_detected_newline_type;
}; };
/*
* Class definition
*/
typedef struct _XedDocumentLoaderClass XedDocumentLoaderClass;
struct _XedDocumentLoaderClass struct _XedDocumentLoaderClass
{ {
GObjectClass parent_class; GObjectClass parent_class;
@ -82,21 +62,13 @@ struct _XedDocumentLoaderClass
void (* loading) (XedDocumentLoader *loader, void (* loading) (XedDocumentLoader *loader,
gboolean completed, gboolean completed,
const GError *error); const GError *error);
/* VTable */
void (* load) (XedDocumentLoader *loader);
gboolean (* cancel) (XedDocumentLoader *loader);
goffset (* get_bytes_read) (XedDocumentLoader *loader);
}; };
/*
* Public methods
*/
GType xed_document_loader_get_type (void) G_GNUC_CONST; GType xed_document_loader_get_type (void) G_GNUC_CONST;
/* If enconding == NULL, the encoding will be autodetected */ /* If enconding == NULL, the encoding will be autodetected */
XedDocumentLoader *xed_document_loader_new (XedDocument *doc, XedDocumentLoader *xed_document_loader_new (XedDocument *doc,
const gchar *uri, GFile *location,
const XedEncoding *encoding); const XedEncoding *encoding);
void xed_document_loader_loading (XedDocumentLoader *loader, void xed_document_loader_loading (XedDocumentLoader *loader,
@ -113,7 +85,7 @@ XedDocument *xed_document_loader_get_document (XedDocumentLoader *loader);
/* Returns STDIN_URI if loading from stdin */ /* Returns STDIN_URI if loading from stdin */
#define STDIN_URI "stdin:" #define STDIN_URI "stdin:"
const gchar *xed_document_loader_get_uri (XedDocumentLoader *loader); GFile *xed_document_loader_get_location (XedDocumentLoader *loader);
const XedEncoding *xed_document_loader_get_encoding (XedDocumentLoader *loader); const XedEncoding *xed_document_loader_get_encoding (XedDocumentLoader *loader);

View File

@ -31,42 +31,87 @@
#include <config.h> #include <config.h>
#endif #endif
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <glib/gi18n.h> #include <glib/gi18n.h>
#include <glib.h>
#include <gio/gio.h>
#include <string.h>
#include "xed-document-saver.h" #include "xed-document-saver.h"
#include "xed-debug.h" #include "xed-debug.h"
#include "xed-document-input-stream.h"
#include "xed-prefs-manager.h" #include "xed-prefs-manager.h"
#include "xed-marshal.h" #include "xed-marshal.h"
#include "xed-utils.h" #include "xed-utils.h"
#include "xed-enum-types.h" #include "xed-enum-types.h"
#include "xed-gio-document-saver.h"
G_DEFINE_ABSTRACT_TYPE(XedDocumentSaver, xed_document_saver, G_TYPE_OBJECT) #define WRITE_CHUNK_SIZE 8192
/* Signals */ enum
{
enum {
SAVING, SAVING,
LAST_SIGNAL LAST_SIGNAL
}; };
static guint signals[LAST_SIGNAL] = { 0 }; static guint signals[LAST_SIGNAL] = { 0 };
/* Properties */ enum
{
enum {
PROP_0, PROP_0,
PROP_DOCUMENT, PROP_DOCUMENT,
PROP_URI, PROP_LOCATION,
PROP_ENCODING, PROP_ENCODING,
PROP_NEWLINE_TYPE, PROP_NEWLINE_TYPE,
PROP_FLAGS PROP_FLAGS
}; };
typedef struct
{
XedDocumentSaver *saver;
gchar buffer[WRITE_CHUNK_SIZE];
GCancellable *cancellable;
gboolean tried_mount;
gssize written;
gssize read;
GError *error;
}AsyncData;
#define REMOTE_QUERY_ATTRIBUTES G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE "," \
G_FILE_ATTRIBUTE_TIME_MODIFIED
#define XED_DOCUMENT_SAVER_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), \
XED_TYPE_DOCUMENT_SAVER, \
XedDocumentSaverPrivate))
static void check_modified_async (AsyncData *async);
struct _XedDocumentSaverPrivate
{
GFileInfo *info;
XedDocument *document;
gboolean used;
GFile *location;
const XedEncoding *encoding;
XedDocumentNewlineType newline_type;
XedDocumentSaveFlags flags;
gboolean keep_backup;
GTimeVal old_mtime;
goffset size;
goffset bytes_written;
GCancellable *cancellable;
GOutputStream *stream;
GInputStream *input;
GError *error;
};
G_DEFINE_TYPE(XedDocumentSaver, xed_document_saver, G_TYPE_OBJECT)
static void static void
xed_document_saver_set_property (GObject *object, xed_document_saver_set_property (GObject *object,
guint prop_id, guint prop_id,
@ -78,22 +123,22 @@ xed_document_saver_set_property (GObject *object,
switch (prop_id) switch (prop_id)
{ {
case PROP_DOCUMENT: case PROP_DOCUMENT:
g_return_if_fail (saver->document == NULL); g_return_if_fail (saver->priv->document == NULL);
saver->document = g_value_get_object (value); saver->priv->document = g_value_get_object (value);
break; break;
case PROP_URI: case PROP_LOCATION:
g_return_if_fail (saver->uri == NULL); g_return_if_fail (saver->priv->location == NULL);
saver->uri = g_value_dup_string (value); saver->priv->location = g_value_dup_object (value);
break; break;
case PROP_ENCODING: case PROP_ENCODING:
g_return_if_fail (saver->encoding == NULL); g_return_if_fail (saver->priv->encoding == NULL);
saver->encoding = g_value_get_boxed (value); saver->priv->encoding = g_value_get_boxed (value);
break; break;
case PROP_NEWLINE_TYPE: case PROP_NEWLINE_TYPE:
saver->newline_type = g_value_get_enum (value); saver->priv->newline_type = g_value_get_enum (value);
break; break;
case PROP_FLAGS: case PROP_FLAGS:
saver->flags = g_value_get_flags (value); saver->priv->flags = g_value_get_flags (value);
break; break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@ -112,19 +157,19 @@ xed_document_saver_get_property (GObject *object,
switch (prop_id) switch (prop_id)
{ {
case PROP_DOCUMENT: case PROP_DOCUMENT:
g_value_set_object (value, saver->document); g_value_set_object (value, saver->priv->document);
break; break;
case PROP_URI: case PROP_LOCATION:
g_value_set_string (value, saver->uri); g_value_set_object (value, saver->priv->location);
break; break;
case PROP_ENCODING: case PROP_ENCODING:
g_value_set_boxed (value, saver->encoding); g_value_set_boxed (value, saver->priv->encoding);
break; break;
case PROP_NEWLINE_TYPE: case PROP_NEWLINE_TYPE:
g_value_set_enum (value, saver->newline_type); g_value_set_enum (value, saver->priv->newline_type);
break; break;
case PROP_FLAGS: case PROP_FLAGS:
g_value_set_flags (value, saver->flags); g_value_set_flags (value, saver->priv->flags);
break; break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@ -132,36 +177,87 @@ xed_document_saver_get_property (GObject *object,
} }
} }
static void
xed_document_saver_finalize (GObject *object)
{
XedDocumentSaver *saver = XED_DOCUMENT_SAVER (object);
g_free (saver->uri);
G_OBJECT_CLASS (xed_document_saver_parent_class)->finalize (object);
}
static void static void
xed_document_saver_dispose (GObject *object) xed_document_saver_dispose (GObject *object)
{ {
XedDocumentSaver *saver = XED_DOCUMENT_SAVER (object); XedDocumentSaverPrivate *priv = XED_DOCUMENT_SAVER (object)->priv;
if (saver->info != NULL) if (priv->cancellable != NULL)
{ {
g_object_unref (saver->info); g_cancellable_cancel (priv->cancellable);
saver->info = NULL; g_object_unref (priv->cancellable);
priv->cancellable = NULL;
}
if (priv->error != NULL)
{
g_error_free (priv->error);
priv->error = NULL;
}
if (priv->stream != NULL)
{
g_object_unref (priv->stream);
priv->stream = NULL;
}
if (priv->input != NULL)
{
g_object_unref (priv->input);
priv->input = NULL;
}
if (priv->info != NULL)
{
g_object_unref (priv->info);
priv->info = NULL;
}
if (priv->location != NULL)
{
g_object_unref (priv->location);
priv->location = NULL;
} }
G_OBJECT_CLASS (xed_document_saver_parent_class)->dispose (object); G_OBJECT_CLASS (xed_document_saver_parent_class)->dispose (object);
} }
static AsyncData *
async_data_new (XedDocumentSaver *saver)
{
AsyncData *async;
async = g_slice_new (AsyncData);
async->saver = saver;
async->cancellable = g_object_ref (saver->priv->cancellable);
async->tried_mount = FALSE;
async->written = 0;
async->read = 0;
async->error = NULL;
return async;
}
static void
async_data_free (AsyncData *async)
{
g_object_ref (async->cancellable);
if (async->error)
{
g_error_free (async->error);
}
g_slice_free (AsyncData, async);
}
static void static void
xed_document_saver_class_init (XedDocumentSaverClass *klass) xed_document_saver_class_init (XedDocumentSaverClass *klass)
{ {
GObjectClass *object_class = G_OBJECT_CLASS (klass); GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = xed_document_saver_finalize;
object_class->dispose = xed_document_saver_dispose; object_class->dispose = xed_document_saver_dispose;
object_class->set_property = xed_document_saver_set_property; object_class->set_property = xed_document_saver_set_property;
object_class->get_property = xed_document_saver_get_property; object_class->get_property = xed_document_saver_get_property;
@ -177,11 +273,11 @@ xed_document_saver_class_init (XedDocumentSaverClass *klass)
G_PARAM_STATIC_STRINGS)); G_PARAM_STATIC_STRINGS));
g_object_class_install_property (object_class, g_object_class_install_property (object_class,
PROP_URI, PROP_LOCATION,
g_param_spec_string ("uri", g_param_spec_object ("location",
"URI", "LOCATION",
"The URI this XedDocumentSaver saves the document to", "The LOCATION this XedDocumentSaver saves the document to",
"", G_TYPE_FILE,
G_PARAM_READWRITE | G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY | G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS)); G_PARAM_STATIC_STRINGS));
@ -189,7 +285,7 @@ xed_document_saver_class_init (XedDocumentSaverClass *klass)
g_object_class_install_property (object_class, g_object_class_install_property (object_class,
PROP_ENCODING, PROP_ENCODING,
g_param_spec_boxed ("encoding", g_param_spec_boxed ("encoding",
"URI", "ENCODING",
"The encoding of the saved file", "The encoding of the saved file",
XED_TYPE_ENCODING, XED_TYPE_ENCODING,
G_PARAM_READWRITE | G_PARAM_READWRITE |
@ -229,40 +325,630 @@ xed_document_saver_class_init (XedDocumentSaverClass *klass)
2, 2,
G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
G_TYPE_POINTER); G_TYPE_POINTER);
g_type_class_add_private (object_class, sizeof (XedDocumentSaverPrivate));
} }
static void static void
xed_document_saver_init (XedDocumentSaver *saver) xed_document_saver_init (XedDocumentSaver *saver)
{ {
saver->used = FALSE; saver->priv = XED_DOCUMENT_SAVER_GET_PRIVATE (saver);
saver->priv->cancellable = g_cancellable_new ();
saver->priv->error = NULL;
saver->priv->used = FALSE;
} }
XedDocumentSaver * XedDocumentSaver *
xed_document_saver_new (XedDocument *doc, xed_document_saver_new (XedDocument *doc,
const gchar *uri, GFile *location,
const XedEncoding *encoding, const XedEncoding *encoding,
XedDocumentNewlineType newline_type, XedDocumentNewlineType newline_type,
XedDocumentSaveFlags flags) XedDocumentSaveFlags flags)
{ {
XedDocumentSaver *saver;
GType saver_type;
g_return_val_if_fail (XED_IS_DOCUMENT (doc), NULL); g_return_val_if_fail (XED_IS_DOCUMENT (doc), NULL);
saver_type = XED_TYPE_GIO_DOCUMENT_SAVER;
if (encoding == NULL) if (encoding == NULL)
{
encoding = xed_encoding_get_utf8 (); encoding = xed_encoding_get_utf8 ();
}
saver = XED_DOCUMENT_SAVER (g_object_new (saver_type, return XED_DOCUMENT_SAVER (g_object_new (XED_TYPE_DOCUMENT_SAVER,
"document", doc, "document", doc,
"uri", uri, "location", location,
"encoding", encoding, "encoding", encoding,
"newline_type", newline_type, "newline_type", newline_type,
"flags", flags, "flags", flags,
NULL)); NULL));
}
return saver; static void
remote_save_completed_or_failed (XedDocumentSaver *saver,
AsyncData *async)
{
xed_document_saver_saving (saver, TRUE, saver->priv->error);
if (async)
{
async_data_free (async);
}
}
static void
async_failed (AsyncData *async,
GError *error)
{
g_propagate_error (&async->saver->priv->error, error);
remote_save_completed_or_failed (async->saver, async);
}
/* BEGIN NOTE:
*
* This fixes an issue in GOutputStream that applies the atomic replace
* save strategy. The stream moves the written file to the original file
* when the stream is closed. However, there is no way currently to tell
* the stream that the save should be aborted (there could be a
* conversion error). The patch explicitly closes the output stream
* in all these cases with a GCancellable in the cancelled state, causing
* the output stream to close, but not move the file. This makes use
* of an implementation detail in the local file stream and should be
* properly fixed by adding the appropriate API in . Until then, at least
* we prevent data corruption for now.
*
* Relevant bug reports:
*
* Bug 615110 - write file ignore encoding errors (gedit)
* https://bugzilla.gnome.org/show_bug.cgi?id=615110
*
* Bug 602412 - g_file_replace does not restore original file when there is
* errors while writing (glib/)
* https://bugzilla.gnome.org/show_bug.cgi?id=602412
*/
static void
cancel_output_stream_ready_cb (GOutputStream *stream,
GAsyncResult *result,
AsyncData *async)
{
GError *error;
g_output_stream_close_finish (stream, result, NULL);
/* check cancelled state manually */
if (g_cancellable_is_cancelled (async->cancellable) || async->error == NULL)
{
async_data_free (async);
return;
}
error = async->error;
async->error = NULL;
async_failed (async, error);
}
static void
cancel_output_stream (AsyncData *async)
{
GCancellable *cancellable;
xed_debug_message (DEBUG_SAVER, "Cancel output stream");
cancellable = g_cancellable_new ();
g_cancellable_cancel (cancellable);
g_output_stream_close_async (async->saver->priv->stream,
G_PRIORITY_HIGH,
cancellable,
(GAsyncReadyCallback)cancel_output_stream_ready_cb,
async);
g_object_unref (cancellable);
}
static void
cancel_output_stream_and_fail (AsyncData *async,
GError *error)
{
xed_debug_message (DEBUG_SAVER, "Cancel output stream and fail");
g_propagate_error (&async->error, error);
cancel_output_stream (async);
}
/*
* END NOTE
*/
static void
remote_get_info_cb (GFile *source,
GAsyncResult *res,
AsyncData *async)
{
XedDocumentSaver *saver;
GFileInfo *info;
GError *error = NULL;
xed_debug (DEBUG_SAVER);
/* check cancelled state manually */
if (g_cancellable_is_cancelled (async->cancellable))
{
async_data_free (async);
return;
}
saver = async->saver;
xed_debug_message (DEBUG_SAVER, "Finished query info on file");
info = g_file_query_info_finish (source, res, &error);
if (info != NULL)
{
if (saver->priv->info != NULL)
{
g_object_unref (saver->priv->info);
}
saver->priv->info = info;
}
else
{
xed_debug_message (DEBUG_SAVER, "Query info failed: %s", error->message);
g_propagate_error (&saver->priv->error, error);
}
remote_save_completed_or_failed (saver, async);
}
static void
close_async_ready_get_info_cb (GOutputStream *stream,
GAsyncResult *res,
AsyncData *async)
{
GError *error = NULL;
xed_debug (DEBUG_SAVER);
/* check cancelled state manually */
if (g_cancellable_is_cancelled (async->cancellable))
{
async_data_free (async);
return;
}
xed_debug_message (DEBUG_SAVER, "Finished closing stream");
if (!g_output_stream_close_finish (stream, res, &error))
{
xed_debug_message (DEBUG_SAVER, "Closing stream error: %s", error->message);
async_failed (async, error);
return;
}
/* get the file info: note we cannot use
* g_file_output_stream_query_info_async since it is not able to get the
* content type etc, beside it is not supported by gvfs.
* I'm not sure this is actually necessary, can't we just use
* g_content_type_guess (since we have the file name and the data)
*/
xed_debug_message (DEBUG_SAVER, "Query info on file");
g_file_query_info_async (async->saver->priv->location,
REMOTE_QUERY_ATTRIBUTES,
G_FILE_QUERY_INFO_NONE,
G_PRIORITY_HIGH,
async->cancellable,
(GAsyncReadyCallback) remote_get_info_cb,
async);
}
static void
write_complete (AsyncData *async)
{
GError *error = NULL;
/* first we close the input stream */
xed_debug_message (DEBUG_SAVER, "Close input stream");
if (!g_input_stream_close (async->saver->priv->input, async->cancellable, &error))
{
xed_debug_message (DEBUG_SAVER, "Closing input stream error: %s", error->message);
cancel_output_stream_and_fail (async, error);
return;
}
/* now we close the output stream */
xed_debug_message (DEBUG_SAVER, "Close output stream");
g_output_stream_close_async (async->saver->priv->stream,
G_PRIORITY_HIGH,
async->cancellable,
(GAsyncReadyCallback)close_async_ready_get_info_cb,
async);
}
static void read_file_chunk (AsyncData *async);
static void write_file_chunk (AsyncData *async);
static void
async_write_cb (GOutputStream *stream,
GAsyncResult *res,
AsyncData *async)
{
XedDocumentSaver *saver;
gssize bytes_written;
GError *error = NULL;
xed_debug (DEBUG_SAVER);
/* Check cancelled state manually */
if (g_cancellable_is_cancelled (async->cancellable))
{
cancel_output_stream (async);
return;
}
bytes_written = g_output_stream_write_finish (stream, res, &error);
xed_debug_message (DEBUG_SAVER, "Written: %" G_GSSIZE_FORMAT, bytes_written);
if (bytes_written == -1)
{
xed_debug_message (DEBUG_SAVER, "Write error: %s", error->message);
cancel_output_stream_and_fail (async, error);
return;
}
saver = async->saver;
async->written += bytes_written;
/* write again */
if (async->written != async->read)
{
write_file_chunk (async);
return;
}
/* note that this signal blocks the write... check if it isn't
* a performance problem
*/
xed_document_saver_saving (saver, FALSE, NULL);
read_file_chunk (async);
}
static void
write_file_chunk (AsyncData *async)
{
XedDocumentSaver *saver;
xed_debug (DEBUG_SAVER);
saver = async->saver;
g_output_stream_write_async (G_OUTPUT_STREAM (saver->priv->stream),
async->buffer + async->written,
async->read - async->written,
G_PRIORITY_HIGH,
async->cancellable,
(GAsyncReadyCallback) async_write_cb,
async);
}
static void
read_file_chunk (AsyncData *async)
{
XedDocumentSaver *saver;
XedDocumentInputStream *dstream;
GError *error = NULL;
xed_debug (DEBUG_SAVER);
saver = async->saver;
async->written = 0;
/* we use sync methods on doc stream since it is in memory. Using async
would be racy and we can endup with invalidated iters */
async->read = g_input_stream_read (saver->priv->input,
async->buffer,
WRITE_CHUNK_SIZE,
async->cancellable,
&error);
if (error != NULL)
{
cancel_output_stream_and_fail (async, error);
return;
}
/* Check if we finished reading and writing */
if (async->read == 0)
{
write_complete (async);
return;
}
/* Get how many chars have been read */
dstream = XED_DOCUMENT_INPUT_STREAM (saver->priv->input);
saver->priv->bytes_written = xed_document_input_stream_tell (dstream);
write_file_chunk (async);
}
static void
async_replace_ready_callback (GFile *source,
GAsyncResult *res,
AsyncData *async)
{
XedDocumentSaver *saver;
GCharsetConverter *converter;
GFileOutputStream *file_stream;
GError *error = NULL;
xed_debug (DEBUG_SAVER);
/* Check cancelled state manually */
if (g_cancellable_is_cancelled (async->cancellable))
{
async_data_free (async);
return;
}
saver = async->saver;
file_stream = g_file_replace_finish (source, res, &error);
/* handle any error that might occur */
if (!file_stream)
{
xed_debug_message (DEBUG_SAVER, "Opening file failed: %s", error->message);
async_failed (async, error);
return;
}
/* FIXME: manage converter error? */
xed_debug_message (DEBUG_SAVER, "Encoding charset: %s", xed_encoding_get_charset (saver->priv->encoding));
if (saver->priv->encoding != xed_encoding_get_utf8 ())
{
converter = g_charset_converter_new (xed_encoding_get_charset (saver->priv->encoding), "UTF-8", NULL);
saver->priv->stream = g_converter_output_stream_new (G_OUTPUT_STREAM (file_stream), G_CONVERTER (converter));
g_object_unref (file_stream);
g_object_unref (converter);
}
else
{
saver->priv->stream = G_OUTPUT_STREAM (file_stream);
}
saver->priv->input = xed_document_input_stream_new (GTK_TEXT_BUFFER (saver->priv->document),
saver->priv->newline_type);
saver->priv->size = xed_document_input_stream_get_total_size (XED_DOCUMENT_INPUT_STREAM (saver->priv->input));
read_file_chunk (async);
}
static void
begin_write (AsyncData *async)
{
XedDocumentSaver *saver;
gboolean backup;
xed_debug_message (DEBUG_SAVER, "Start replacing file contents");
/* For remote files we simply use g_file_replace_async. There is no
* backup as of yet
*/
saver = async->saver;
/* Do not make backups for remote files so they do not clutter remote systems */
backup = (saver->priv->keep_backup && xed_document_is_local (saver->priv->document));
xed_debug_message (DEBUG_SAVER, "File contents size: %" G_GINT64_FORMAT, saver->priv->size);
xed_debug_message (DEBUG_SAVER, "Calling replace_async");
xed_debug_message (DEBUG_SAVER, backup ? "Keep backup" : "Discard backup");
g_file_replace_async (saver->priv->location,
NULL,
backup,
G_FILE_CREATE_NONE,
G_PRIORITY_HIGH,
async->cancellable,
(GAsyncReadyCallback) async_replace_ready_callback,
async);
}
static void
mount_ready_callback (GFile *file,
GAsyncResult *res,
AsyncData *async)
{
GError *error = NULL;
gboolean mounted;
xed_debug (DEBUG_SAVER);
/* manual check for cancelled state */
if (g_cancellable_is_cancelled (async->cancellable))
{
async_data_free (async);
return;
}
mounted = g_file_mount_enclosing_volume_finish (file, res, &error);
if (!mounted)
{
async_failed (async, error);
}
else
{
/* try again to get the modified state */
check_modified_async (async);
}
}
static void
recover_not_mounted (AsyncData *async)
{
XedDocument *doc;
GMountOperation *mount_operation;
xed_debug (DEBUG_LOADER);
doc = xed_document_saver_get_document (async->saver);
mount_operation = _xed_document_create_mount_operation (doc);
async->tried_mount = TRUE;
g_file_mount_enclosing_volume (async->saver->priv->location,
G_MOUNT_MOUNT_NONE,
mount_operation,
async->cancellable,
(GAsyncReadyCallback) mount_ready_callback,
async);
g_object_unref (mount_operation);
}
static void
check_modification_callback (GFile *source,
GAsyncResult *res,
AsyncData *async)
{
XedDocumentSaver *saver;
GError *error = NULL;
GFileInfo *info;
xed_debug (DEBUG_SAVER);
/* manually check cancelled state */
if (g_cancellable_is_cancelled (async->cancellable))
{
async_data_free (async);
return;
}
saver = async->saver;
info = g_file_query_info_finish (source, res, &error);
if (info == NULL)
{
if (error->code == G_IO_ERROR_NOT_MOUNTED && !async->tried_mount)
{
recover_not_mounted (async);
g_error_free (error);
return;
}
/* it's perfectly fine if the file doesn't exist yet */
if (error->code != G_IO_ERROR_NOT_FOUND)
{
xed_debug_message (DEBUG_SAVER, "Error getting modification: %s", error->message);
async_failed (async, error);
return;
}
}
/* check if the mtime is > what we know about it (if we have it) */
if (info != NULL && g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_TIME_MODIFIED))
{
GTimeVal mtime;
GTimeVal old_mtime;
g_file_info_get_modification_time (info, &mtime);
old_mtime = saver->priv->old_mtime;
if ((old_mtime.tv_sec > 0 || old_mtime.tv_usec > 0) &&
(mtime.tv_sec != old_mtime.tv_sec || mtime.tv_usec != old_mtime.tv_usec) &&
(saver->priv->flags & XED_DOCUMENT_SAVE_IGNORE_MTIME) == 0)
{
xed_debug_message (DEBUG_SAVER, "File is externally modified");
g_set_error (&saver->priv->error,
XED_DOCUMENT_ERROR,
XED_DOCUMENT_ERROR_EXTERNALLY_MODIFIED,
"Externally modified");
remote_save_completed_or_failed (saver, async);
g_object_unref (info);
return;
}
}
if (info != NULL)
{
g_object_unref (info);
}
/* modification check passed, start write */
begin_write (async);
}
static void
check_modified_async (AsyncData *async)
{
xed_debug_message (DEBUG_SAVER, "Check externally modified");
g_file_query_info_async (async->saver->priv->location,
G_FILE_ATTRIBUTE_TIME_MODIFIED,
G_FILE_QUERY_INFO_NONE,
G_PRIORITY_HIGH,
async->cancellable,
(GAsyncReadyCallback) check_modification_callback,
async);
}
static gboolean
save_remote_file_real (XedDocumentSaver *saver)
{
AsyncData *async;
xed_debug_message (DEBUG_SAVER, "Starting save");
/* First find out if the file is modified externally. This requires
* a stat, but I don't think we can do this any other way
*/
async = async_data_new (saver);
check_modified_async (async);
/* return false to stop timeout */
return FALSE;
}
void
xed_document_saver_save (XedDocumentSaver *saver,
GTimeVal *old_mtime)
{
xed_debug (DEBUG_SAVER);
g_return_if_fail (XED_IS_DOCUMENT_SAVER (saver));
g_return_if_fail (saver->priv->location != NULL);
g_return_if_fail (saver->priv->used == FALSE);
saver->priv->used = TRUE;
/* CHECK:
report async (in an idle handler) or sync (bool ret)
async is extra work here, sync is special casing in the caller */
/* never keep backup of autosaves */
if ((saver->priv->flags & XED_DOCUMENT_SAVE_PRESERVE_BACKUP) != 0)
{
saver->priv->keep_backup = FALSE;
}
else
{
saver->priv->keep_backup = xed_prefs_manager_get_create_backup_copy ();
}
saver->priv->old_mtime = *old_mtime;
/* saving start */
xed_document_saver_saving (saver, FALSE, NULL);
g_timeout_add_full (G_PRIORITY_HIGH, 0, (GSourceFunc) save_remote_file_real, saver, NULL);
} }
void void
@ -291,46 +977,20 @@ xed_document_saver_saving (XedDocumentSaver *saver,
} }
} }
void
xed_document_saver_save (XedDocumentSaver *saver,
GTimeVal *old_mtime)
{
xed_debug (DEBUG_SAVER);
g_return_if_fail (XED_IS_DOCUMENT_SAVER (saver));
g_return_if_fail (saver->uri != NULL && strlen (saver->uri) > 0);
g_return_if_fail (saver->used == FALSE);
saver->used = TRUE;
// CHECK:
// - sanity check a max len for the uri?
// report async (in an idle handler) or sync (bool ret)
// async is extra work here, sync is special casing in the caller
/* never keep backup of autosaves */
if ((saver->flags & XED_DOCUMENT_SAVE_PRESERVE_BACKUP) != 0)
saver->keep_backup = FALSE;
else
saver->keep_backup = xed_prefs_manager_get_create_backup_copy ();
XED_DOCUMENT_SAVER_GET_CLASS (saver)->save (saver, old_mtime);
}
XedDocument * XedDocument *
xed_document_saver_get_document (XedDocumentSaver *saver) xed_document_saver_get_document (XedDocumentSaver *saver)
{ {
g_return_val_if_fail (XED_IS_DOCUMENT_SAVER (saver), NULL); g_return_val_if_fail (XED_IS_DOCUMENT_SAVER (saver), NULL);
return saver->document; return saver->priv->document;
} }
const gchar * GFile *
xed_document_saver_get_uri (XedDocumentSaver *saver) xed_document_saver_get_location (XedDocumentSaver *saver)
{ {
g_return_val_if_fail (XED_IS_DOCUMENT_SAVER (saver), NULL); g_return_val_if_fail (XED_IS_DOCUMENT_SAVER (saver), NULL);
return saver->uri; return g_file_dup (saver->priv->location);
} }
/* Returns 0 if file size is unknown */ /* Returns 0 if file size is unknown */
@ -339,7 +999,7 @@ xed_document_saver_get_file_size (XedDocumentSaver *saver)
{ {
g_return_val_if_fail (XED_IS_DOCUMENT_SAVER (saver), 0); g_return_val_if_fail (XED_IS_DOCUMENT_SAVER (saver), 0);
return XED_DOCUMENT_SAVER_GET_CLASS (saver)->get_file_size (saver); return saver->priv->size;
} }
goffset goffset
@ -347,7 +1007,7 @@ xed_document_saver_get_bytes_written (XedDocumentSaver *saver)
{ {
g_return_val_if_fail (XED_IS_DOCUMENT_SAVER (saver), 0); g_return_val_if_fail (XED_IS_DOCUMENT_SAVER (saver), 0);
return XED_DOCUMENT_SAVER_GET_CLASS (saver)->get_bytes_written (saver); return saver->priv->bytes_written;
} }
GFileInfo * GFileInfo *
@ -355,5 +1015,5 @@ xed_document_saver_get_info (XedDocumentSaver *saver)
{ {
g_return_val_if_fail (XED_IS_DOCUMENT_SAVER (saver), NULL); g_return_val_if_fail (XED_IS_DOCUMENT_SAVER (saver), NULL);
return saver->info; return saver->priv->info;
} }

View File

@ -25,8 +25,6 @@
* Modified by the xed Team, 2005. See the AUTHORS file for a * Modified by the xed Team, 2005. See the AUTHORS file for a
* list of people on the xed Team. * list of people on the xed Team.
* See the ChangeLog files for a list of changes. * See the ChangeLog files for a list of changes.
*
* $Id$
*/ */
#ifndef __XED_DOCUMENT_SAVER_H__ #ifndef __XED_DOCUMENT_SAVER_H__
@ -36,9 +34,6 @@
G_BEGIN_DECLS G_BEGIN_DECLS
/*
* Type checking and casting macros
*/
#define XED_TYPE_DOCUMENT_SAVER (xed_document_saver_get_type()) #define XED_TYPE_DOCUMENT_SAVER (xed_document_saver_get_type())
#define XED_DOCUMENT_SAVER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), XED_TYPE_DOCUMENT_SAVER, XedDocumentSaver)) #define XED_DOCUMENT_SAVER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), XED_TYPE_DOCUMENT_SAVER, XedDocumentSaver))
#define XED_DOCUMENT_SAVER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), XED_TYPE_DOCUMENT_SAVER, XedDocumentSaverClass)) #define XED_DOCUMENT_SAVER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), XED_TYPE_DOCUMENT_SAVER, XedDocumentSaverClass))
@ -46,34 +41,18 @@ G_BEGIN_DECLS
#define XED_IS_DOCUMENT_SAVER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XED_TYPE_DOCUMENT_SAVER)) #define XED_IS_DOCUMENT_SAVER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XED_TYPE_DOCUMENT_SAVER))
#define XED_DOCUMENT_SAVER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), XED_TYPE_DOCUMENT_SAVER, XedDocumentSaverClass)) #define XED_DOCUMENT_SAVER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), XED_TYPE_DOCUMENT_SAVER, XedDocumentSaverClass))
/*
* Main object structure
*/
typedef struct _XedDocumentSaver XedDocumentSaver; typedef struct _XedDocumentSaver XedDocumentSaver;
typedef struct _XedDocumentSaverPrivate XedDocumentSaverPrivate;
typedef struct _XedDocumentSaverClass XedDocumentSaverClass;
struct _XedDocumentSaver struct _XedDocumentSaver
{ {
GObject object; GObject object;
/*< private >*/ /*< private >*/
GFileInfo *info; XedDocumentSaverPrivate *priv;
XedDocument *document;
gboolean used;
gchar *uri;
const XedEncoding *encoding;
XedDocumentNewlineType newline_type;
XedDocumentSaveFlags flags;
gboolean keep_backup;
}; };
/*
* Class definition
*/
typedef struct _XedDocumentSaverClass XedDocumentSaverClass;
struct _XedDocumentSaverClass struct _XedDocumentSaverClass
{ {
GObjectClass parent_class; GObjectClass parent_class;
@ -82,22 +61,13 @@ struct _XedDocumentSaverClass
void (* saving) (XedDocumentSaver *saver, void (* saving) (XedDocumentSaver *saver,
gboolean completed, gboolean completed,
const GError *error); const GError *error);
/* VTable */
void (* save) (XedDocumentSaver *saver,
GTimeVal *old_mtime);
goffset (* get_file_size) (XedDocumentSaver *saver);
goffset (* get_bytes_written) (XedDocumentSaver *saver);
}; };
/*
* Public methods
*/
GType xed_document_saver_get_type (void) G_GNUC_CONST; GType xed_document_saver_get_type (void) G_GNUC_CONST;
/* If enconding == NULL, the encoding will be autodetected */ /* If enconding == NULL, the encoding will be autodetected */
XedDocumentSaver *xed_document_saver_new (XedDocument *doc, XedDocumentSaver *xed_document_saver_new (XedDocument *doc,
const gchar *uri, GFile *location,
const XedEncoding *encoding, const XedEncoding *encoding,
XedDocumentNewlineType newline_type, XedDocumentNewlineType newline_type,
XedDocumentSaveFlags flags); XedDocumentSaveFlags flags);
@ -114,7 +84,7 @@ void xed_document_saver_cancel (XedDocumentSaver *saver);
XedDocument *xed_document_saver_get_document (XedDocumentSaver *saver); XedDocument *xed_document_saver_get_document (XedDocumentSaver *saver);
const gchar *xed_document_saver_get_uri (XedDocumentSaver *saver); GFile *xed_document_saver_get_location (XedDocumentSaver *saver);
/* If backup_uri is NULL no backup will be made */ /* If backup_uri is NULL no backup will be made */
const gchar *xed_document_saver_get_backup_uri (XedDocumentSaver *saver); const gchar *xed_document_saver_get_backup_uri (XedDocumentSaver *saver);

View File

@ -80,12 +80,12 @@ PROFILE (static GTimer *timer = NULL)
#define XED_DOCUMENT_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), XED_TYPE_DOCUMENT, XedDocumentPrivate)) #define XED_DOCUMENT_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), XED_TYPE_DOCUMENT, XedDocumentPrivate))
static void xed_document_load_real (XedDocument *doc, static void xed_document_load_real (XedDocument *doc,
const gchar *uri, GFile *location,
const XedEncoding *encoding, const XedEncoding *encoding,
gint line_pos, gint line_pos,
gboolean create); gboolean create);
static void xed_document_save_real (XedDocument *doc, static void xed_document_save_real (XedDocument *doc,
const gchar *uri, GFile *location,
const XedEncoding *encoding, const XedEncoding *encoding,
XedDocumentSaveFlags flags); XedDocumentSaveFlags flags);
static void to_search_region_range (XedDocument *doc, static void to_search_region_range (XedDocument *doc,
@ -102,7 +102,7 @@ static void delete_range_cb (XedDocument *doc,
struct _XedDocumentPrivate struct _XedDocumentPrivate
{ {
gchar *uri; GFile *location;
gint untitled_number; gint untitled_number;
gchar *short_name; gchar *short_name;
@ -150,7 +150,7 @@ enum
{ {
PROP_0, PROP_0,
PROP_URI, PROP_LOCATION,
PROP_SHORTNAME, PROP_SHORTNAME,
PROP_CONTENT_TYPE, PROP_CONTENT_TYPE,
PROP_MIME_TYPE, PROP_MIME_TYPE,
@ -237,7 +237,7 @@ xed_document_dispose (GObject *object)
* because the language is gone by the time finalize runs. * because the language is gone by the time finalize runs.
* beside if some plugin prevents proper finalization by * beside if some plugin prevents proper finalization by
* holding a ref to the doc, we still save the metadata */ * holding a ref to the doc, we still save the metadata */
if ((!doc->priv->dispose_has_run) && (doc->priv->uri != NULL)) if ((!doc->priv->dispose_has_run) && (doc->priv->location != NULL))
{ {
GtkTextIter iter; GtkTextIter iter;
gchar *position; gchar *position;
@ -290,6 +290,12 @@ xed_document_dispose (GObject *object)
doc->priv->metadata_info = NULL; doc->priv->metadata_info = NULL;
} }
if (doc->priv->location != NULL)
{
g_object_unref (doc->priv->location);
doc->priv->location = NULL;
}
doc->priv->dispose_has_run = TRUE; doc->priv->dispose_has_run = TRUE;
G_OBJECT_CLASS (xed_document_parent_class)->dispose (object); G_OBJECT_CLASS (xed_document_parent_class)->dispose (object);
@ -304,11 +310,9 @@ xed_document_finalize (GObject *object)
if (doc->priv->untitled_number > 0) if (doc->priv->untitled_number > 0)
{ {
g_return_if_fail (doc->priv->uri == NULL);
release_untitled_number (doc->priv->untitled_number); release_untitled_number (doc->priv->untitled_number);
} }
g_free (doc->priv->uri);
g_free (doc->priv->content_type); g_free (doc->priv->content_type);
g_free (doc->priv->search_text); g_free (doc->priv->search_text);
@ -331,8 +335,8 @@ xed_document_get_property (GObject *object,
switch (prop_id) switch (prop_id)
{ {
case PROP_URI: case PROP_LOCATION:
g_value_set_string (value, doc->priv->uri); g_value_set_object (value, doc->priv->location);
break; break;
case PROP_SHORTNAME: case PROP_SHORTNAME:
g_value_take_string (value, xed_document_get_short_name_for_display (doc)); g_value_take_string (value, xed_document_get_short_name_for_display (doc));
@ -444,11 +448,11 @@ xed_document_class_init (XedDocumentClass *klass)
klass->load = xed_document_load_real; klass->load = xed_document_load_real;
klass->save = xed_document_save_real; klass->save = xed_document_save_real;
g_object_class_install_property (object_class, PROP_URI, g_object_class_install_property (object_class, PROP_LOCATION,
g_param_spec_string ("uri", g_param_spec_object ("location",
"URI", "LOCATION",
"The document's URI", "The document's location",
NULL, G_TYPE_FILE,
G_PARAM_READABLE | G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS)); G_PARAM_STATIC_STRINGS));
@ -543,7 +547,7 @@ xed_document_class_init (XedDocumentClass *klass)
/** /**
* XedDocument::load: * XedDocument::load:
* @document: the #XedDocument. * @document: the #XedDocument.
* @uri: the uri where to load the document from. * @location: the location where to load the document from.
* @encoding: the #XedEncoding to encode the document. * @encoding: the #XedEncoding to encode the document.
* @line_pos: the line to show. * @line_pos: the line to show.
* @create: whether the document should be created if it doesn't exist. * @create: whether the document should be created if it doesn't exist.
@ -556,10 +560,10 @@ xed_document_class_init (XedDocumentClass *klass)
G_SIGNAL_RUN_LAST, G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (XedDocumentClass, load), G_STRUCT_OFFSET (XedDocumentClass, load),
NULL, NULL, NULL, NULL,
xed_marshal_VOID__STRING_BOXED_INT_BOOLEAN, xed_marshal_VOID__OBJECT_BOXED_INT_BOOLEAN,
G_TYPE_NONE, G_TYPE_NONE,
4, 4,
G_TYPE_STRING, G_TYPE_FILE,
/* we rely on the fact that the XedEncoding pointer stays /* we rely on the fact that the XedEncoding pointer stays
* the same forever */ * the same forever */
XED_TYPE_ENCODING | G_SIGNAL_TYPE_STATIC_SCOPE, XED_TYPE_ENCODING | G_SIGNAL_TYPE_STATIC_SCOPE,
@ -593,7 +597,7 @@ xed_document_class_init (XedDocumentClass *klass)
/** /**
* XedDocument::save: * XedDocument::save:
* @document: the #XedDocument. * @document: the #XedDocument.
* @uri: the uri where the document is about to be saved. * @location: the location where the document is about to be saved.
* @encoding: the #XedEncoding used to save the document. * @encoding: the #XedEncoding used to save the document.
* @flags: the #XedDocumentSaveFlags for the save operation. * @flags: the #XedDocumentSaveFlags for the save operation.
* *
@ -605,10 +609,10 @@ xed_document_class_init (XedDocumentClass *klass)
G_SIGNAL_RUN_LAST, G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (XedDocumentClass, save), G_STRUCT_OFFSET (XedDocumentClass, save),
NULL, NULL, NULL, NULL,
xed_marshal_VOID__STRING_BOXED_FLAGS, xed_marshal_VOID__OBJECT_BOXED_FLAGS,
G_TYPE_NONE, G_TYPE_NONE,
3, 3,
G_TYPE_STRING, G_TYPE_FILE,
/* we rely on the fact that the XedEncoding pointer stays /* we rely on the fact that the XedEncoding pointer stays
* the same forever */ * the same forever */
XED_TYPE_ENCODING | G_SIGNAL_TYPE_STATIC_SCOPE, XED_TYPE_ENCODING | G_SIGNAL_TYPE_STATIC_SCOPE,
@ -680,7 +684,7 @@ set_language (XedDocument *doc,
gtk_source_buffer_set_highlight_syntax (GTK_SOURCE_BUFFER (doc), FALSE); gtk_source_buffer_set_highlight_syntax (GTK_SOURCE_BUFFER (doc), FALSE);
} }
if (set_by_user && (doc->priv->uri != NULL)) if (set_by_user)
{ {
xed_document_set_metadata (doc, XED_METADATA_ATTRIBUTE_LANGUAGE, xed_document_set_metadata (doc, XED_METADATA_ATTRIBUTE_LANGUAGE,
(lang == NULL) ? "_NORMAL_" : gtk_source_language_get_id (lang), (lang == NULL) ? "_NORMAL_" : gtk_source_language_get_id (lang),
@ -747,7 +751,7 @@ get_default_style_scheme (void)
} }
static void static void
on_uri_changed (XedDocument *doc, on_location_changed (XedDocument *doc,
GParamSpec *pspec, GParamSpec *pspec,
gpointer useless) gpointer useless)
{ {
@ -756,9 +760,9 @@ on_uri_changed (XedDocument *doc,
location = xed_document_get_location (doc); location = xed_document_get_location (doc);
/* load metadata for this uri: we load sync since metadata is /* load metadata for this location: we load sync since metadata is
* always local so it should be fast and we need the information * always local so it should be fast and we need the information
* right after the uri was set. * right after the location was set.
*/ */
if (location != NULL) if (location != NULL)
{ {
@ -814,15 +818,15 @@ guess_language (XedDocument *doc,
} }
else else
{ {
GFile *file; GFile *location;
gchar *basename = NULL; gchar *basename = NULL;
file = xed_document_get_location (doc); location = xed_document_get_location (doc);
xed_debug_message (DEBUG_DOCUMENT, "Sniffing Language"); xed_debug_message (DEBUG_DOCUMENT, "Sniffing Language");
if (file) if (location)
{ {
basename = g_file_get_basename (file); basename = g_file_get_basename (location);
} }
else if (doc->priv->short_name != NULL) else if (doc->priv->short_name != NULL)
{ {
@ -833,9 +837,9 @@ guess_language (XedDocument *doc,
g_free (basename); g_free (basename);
if (file != NULL) if (location != NULL)
{ {
g_object_unref (file); g_object_unref (location);
} }
} }
@ -875,7 +879,7 @@ xed_document_init (XedDocument *doc)
doc->priv = XED_DOCUMENT_GET_PRIVATE (doc); doc->priv = XED_DOCUMENT_GET_PRIVATE (doc);
doc->priv->uri = NULL; doc->priv->location = NULL;
doc->priv->untitled_number = get_untitled_number (); doc->priv->untitled_number = get_untitled_number ();
doc->priv->metadata_info = NULL; doc->priv->metadata_info = NULL;
@ -914,7 +918,7 @@ xed_document_init (XedDocument *doc)
g_signal_connect_after (doc, "insert-text", G_CALLBACK (insert_text_cb), NULL); g_signal_connect_after (doc, "insert-text", G_CALLBACK (insert_text_cb), NULL);
g_signal_connect_after (doc, "delete-range", G_CALLBACK (delete_range_cb), NULL); g_signal_connect_after (doc, "delete-range", G_CALLBACK (delete_range_cb), NULL);
g_signal_connect (doc, "notify::content-type", G_CALLBACK (on_content_type_changed), NULL); g_signal_connect (doc, "notify::content-type", G_CALLBACK (on_content_type_changed), NULL);
g_signal_connect (doc, "notify::uri", G_CALLBACK (on_uri_changed), NULL); g_signal_connect (doc, "notify::location", G_CALLBACK (on_location_changed), NULL);
} }
XedDocument * XedDocument *
@ -959,20 +963,20 @@ set_content_type (XedDocument *doc,
if (content_type == NULL) if (content_type == NULL)
{ {
GFile *file; GFile *location;
gchar *guessed_type = NULL; gchar *guessed_type = NULL;
/* If content type is null, we guess from the filename */ /* If content type is null, we guess from the filename */
file = xed_document_get_location (doc); location = xed_document_get_location (doc);
if (file != NULL) if (location != NULL)
{ {
gchar *basename; gchar *basename;
basename = g_file_get_basename (file); basename = g_file_get_basename (location);
guessed_type = g_content_type_guess (basename, NULL, 0, NULL); guessed_type = g_content_type_guess (basename, NULL, 0, NULL);
g_free (basename); g_free (basename);
g_object_unref (file); g_object_unref (location);
} }
set_content_type_no_guess (doc, guessed_type); set_content_type_no_guess (doc, guessed_type);
@ -1000,22 +1004,26 @@ xed_document_set_content_type (XedDocument *doc,
} }
static void static void
set_uri (XedDocument *doc, set_location (XedDocument *doc,
const gchar *uri) GFile *location)
{ {
xed_debug (DEBUG_DOCUMENT); xed_debug (DEBUG_DOCUMENT);
g_return_if_fail ((uri == NULL) || xed_utils_is_valid_uri (uri)); g_return_if_fail ((location == NULL) || xed_utils_is_valid_location (location));
if (uri != NULL) if (location != NULL)
{ {
if (doc->priv->uri == uri) if (doc->priv->location == location)
{ {
return; return;
} }
g_free (doc->priv->uri); if (doc->priv->location != NULL)
doc->priv->uri = g_strdup (uri); {
g_object_unref (doc->priv->location);
}
doc->priv->location = g_file_dup (location);
if (doc->priv->untitled_number > 0) if (doc->priv->untitled_number > 0)
{ {
@ -1024,7 +1032,7 @@ set_uri (XedDocument *doc,
} }
} }
g_object_notify (G_OBJECT (doc), "uri"); g_object_notify (G_OBJECT (doc), "location");
if (doc->priv->short_name == NULL) if (doc->priv->short_name == NULL)
{ {
@ -1043,25 +1051,17 @@ xed_document_get_location (XedDocument *doc)
{ {
g_return_val_if_fail (XED_IS_DOCUMENT (doc), NULL); g_return_val_if_fail (XED_IS_DOCUMENT (doc), NULL);
return doc->priv->uri == NULL ? NULL : g_file_new_for_uri (doc->priv->uri); return doc->priv->location == NULL ? NULL : g_file_dup (doc->priv->location);
}
gchar *
xed_document_get_uri (XedDocument *doc)
{
g_return_val_if_fail (XED_IS_DOCUMENT (doc), NULL);
return g_strdup (doc->priv->uri);
} }
void void
xed_document_set_uri (XedDocument *doc, xed_document_set_location (XedDocument *doc,
const gchar *uri) GFile *location)
{ {
g_return_if_fail (XED_IS_DOCUMENT (doc)); g_return_if_fail (XED_IS_DOCUMENT (doc));
g_return_if_fail (uri != NULL); g_return_if_fail (G_IS_FILE (location));
set_uri (doc, uri); set_location (doc, location);
set_content_type (doc, NULL); set_content_type (doc, NULL);
} }
@ -1076,13 +1076,13 @@ xed_document_get_uri_for_display (XedDocument *doc)
{ {
g_return_val_if_fail (XED_IS_DOCUMENT (doc), g_strdup ("")); g_return_val_if_fail (XED_IS_DOCUMENT (doc), g_strdup (""));
if (doc->priv->uri == NULL) if (doc->priv->location == NULL)
{ {
return g_strdup_printf (_("Unsaved Document %d"), doc->priv->untitled_number); return g_strdup_printf (_("Unsaved Document %d"), doc->priv->untitled_number);
} }
else else
{ {
return xed_utils_uri_for_display (doc->priv->uri); return xed_utils_uri_for_display (doc->priv->location);
} }
} }
@ -1101,13 +1101,13 @@ xed_document_get_short_name_for_display (XedDocument *doc)
{ {
return g_strdup (doc->priv->short_name); return g_strdup (doc->priv->short_name);
} }
else if (doc->priv->uri == NULL) else if (doc->priv->location == NULL)
{ {
return g_strdup_printf (_("Unsaved Document %d"), doc->priv->untitled_number); return g_strdup_printf (_("Unsaved Document %d"), doc->priv->untitled_number);
} }
else else
{ {
return xed_utils_basename_for_display (doc->priv->uri); return xed_utils_basename_for_display (doc->priv->location);
} }
} }
@ -1209,23 +1209,20 @@ xed_document_get_readonly (XedDocument *doc)
gboolean gboolean
_xed_document_check_externally_modified (XedDocument *doc) _xed_document_check_externally_modified (XedDocument *doc)
{ {
GFile *gfile;
GFileInfo *info; GFileInfo *info;
g_return_val_if_fail (XED_IS_DOCUMENT (doc), FALSE); g_return_val_if_fail (XED_IS_DOCUMENT (doc), FALSE);
if (doc->priv->uri == NULL) if (doc->priv->location == NULL)
{ {
return FALSE; return FALSE;
} }
gfile = g_file_new_for_uri (doc->priv->uri); info = g_file_query_info (doc->priv->location,
info = g_file_query_info (gfile,
G_FILE_ATTRIBUTE_TIME_MODIFIED "," \ G_FILE_ATTRIBUTE_TIME_MODIFIED "," \
G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE,
G_FILE_QUERY_INFO_NONE, G_FILE_QUERY_INFO_NONE,
NULL, NULL); NULL, NULL);
g_object_unref (gfile);
if (info != NULL) if (info != NULL)
{ {
@ -1353,7 +1350,7 @@ document_loader_loaded (XedDocumentLoader *loader,
/* special case creating a named new doc */ /* special case creating a named new doc */
else if (doc->priv->create && else if (doc->priv->create &&
(error->domain == G_IO_ERROR && error->code == G_IO_ERROR_NOT_FOUND) && (error->domain == G_IO_ERROR && error->code == G_IO_ERROR_NOT_FOUND) &&
(xed_utils_uri_has_file_scheme (doc->priv->uri))) (xed_utils_location_has_file_scheme (doc->priv->location)))
{ {
reset_temp_loading_data (doc); reset_temp_loading_data (doc);
@ -1398,17 +1395,21 @@ document_loader_loading (XedDocumentLoader *loader,
static void static void
xed_document_load_real (XedDocument *doc, xed_document_load_real (XedDocument *doc,
const gchar *uri, GFile *location,
const XedEncoding *encoding, const XedEncoding *encoding,
gint line_pos, gint line_pos,
gboolean create) gboolean create)
{ {
gchar *uri;
g_return_if_fail (doc->priv->loader == NULL); g_return_if_fail (doc->priv->loader == NULL);
uri = g_file_get_uri (location);
xed_debug_message (DEBUG_DOCUMENT, "load_real: uri = %s", uri); xed_debug_message (DEBUG_DOCUMENT, "load_real: uri = %s", uri);
g_free (uri);
/* create a loader. It will be destroyed when loading is completed */ /* create a loader. It will be destroyed when loading is completed */
doc->priv->loader = xed_document_loader_new (doc, uri, encoding); doc->priv->loader = xed_document_loader_new (doc, location, encoding);
g_signal_connect (doc->priv->loader, "loading", G_CALLBACK (document_loader_loading), doc); g_signal_connect (doc->priv->loader, "loading", G_CALLBACK (document_loader_loading), doc);
@ -1416,7 +1417,7 @@ xed_document_load_real (XedDocument *doc,
doc->priv->requested_encoding = encoding; doc->priv->requested_encoding = encoding;
doc->priv->requested_line_pos = line_pos; doc->priv->requested_line_pos = line_pos;
set_uri (doc, uri); set_location (doc, location);
set_content_type (doc, NULL); set_content_type (doc, NULL);
xed_document_loader_load (doc->priv->loader); xed_document_loader_load (doc->priv->loader);
@ -1425,7 +1426,7 @@ xed_document_load_real (XedDocument *doc,
/** /**
* xed_document_load: * xed_document_load:
* @doc: the #XedDocument. * @doc: the #XedDocument.
* @uri: the uri where to load the document from. * @location: the location where to load the document from.
* @encoding: the #XedEncoding to encode the document. * @encoding: the #XedEncoding to encode the document.
* @line_pos: the line to show. * @line_pos: the line to show.
* @create: whether the document should be created if it doesn't exist. * @create: whether the document should be created if it doesn't exist.
@ -1434,16 +1435,16 @@ xed_document_load_real (XedDocument *doc,
*/ */
void void
xed_document_load (XedDocument *doc, xed_document_load (XedDocument *doc,
const gchar *uri, GFile *location,
const XedEncoding *encoding, const XedEncoding *encoding,
gint line_pos, gint line_pos,
gboolean create) gboolean create)
{ {
g_return_if_fail (XED_IS_DOCUMENT (doc)); g_return_if_fail (XED_IS_DOCUMENT (doc));
g_return_if_fail (uri != NULL); g_return_if_fail (location != NULL);
g_return_if_fail (xed_utils_is_valid_uri (uri)); g_return_if_fail (xed_utils_is_valid_location (location));
g_signal_emit (doc, document_signals[LOAD], 0, uri, encoding, line_pos, create); g_signal_emit (doc, document_signals[LOAD], 0, location, encoding, line_pos, create);
} }
/** /**
@ -1478,13 +1479,14 @@ document_saver_saving (XedDocumentSaver *saver,
/* save was successful */ /* save was successful */
if (error == NULL) if (error == NULL)
{ {
const gchar *uri; GFile *location;
const gchar *content_type = NULL; const gchar *content_type = NULL;
GTimeVal mtime = {0, 0}; GTimeVal mtime = {0, 0};
GFileInfo *info; GFileInfo *info;
uri = xed_document_saver_get_uri (saver); location = xed_document_saver_get_location (saver);
set_uri (doc, uri); set_location (doc, location);
g_object_unref (location);
info = xed_document_saver_get_info (saver); info = xed_document_saver_get_info (saver);
@ -1533,14 +1535,14 @@ document_saver_saving (XedDocumentSaver *saver,
static void static void
xed_document_save_real (XedDocument *doc, xed_document_save_real (XedDocument *doc,
const gchar *uri, GFile *location,
const XedEncoding *encoding, const XedEncoding *encoding,
XedDocumentSaveFlags flags) XedDocumentSaveFlags flags)
{ {
g_return_if_fail (doc->priv->saver == NULL); g_return_if_fail (doc->priv->saver == NULL);
/* create a saver, it will be destroyed once saving is complete */ /* create a saver, it will be destroyed once saving is complete */
doc->priv->saver = xed_document_saver_new (doc, uri, encoding, doc->priv->newline_type, flags); doc->priv->saver = xed_document_saver_new (doc, location, encoding, doc->priv->newline_type, flags);
g_signal_connect (doc->priv->saver, "saving", G_CALLBACK (document_saver_saving), doc); g_signal_connect (doc->priv->saver, "saving", G_CALLBACK (document_saver_saving), doc);
@ -1562,15 +1564,15 @@ xed_document_save (XedDocument *doc,
XedDocumentSaveFlags flags) XedDocumentSaveFlags flags)
{ {
g_return_if_fail (XED_IS_DOCUMENT (doc)); g_return_if_fail (XED_IS_DOCUMENT (doc));
g_return_if_fail (doc->priv->uri != NULL); g_return_if_fail (G_IS_FILE (doc->priv->location));
g_signal_emit (doc, document_signals[SAVE], 0, doc->priv->uri, doc->priv->encoding, flags); g_signal_emit (doc, document_signals[SAVE], 0, doc->priv->location, doc->priv->encoding, flags);
} }
/** /**
* xed_document_save_as: * xed_document_save_as:
* @doc: the #XedDocument. * @doc: the #XedDocument.
* @uri: the uri where to save the document. * @location: the location where to save the document.
* @encoding: the #XedEncoding to encode the document. * @encoding: the #XedEncoding to encode the document.
* @flags: optionnal #XedDocumentSaveFlags. * @flags: optionnal #XedDocumentSaveFlags.
* *
@ -1579,32 +1581,17 @@ xed_document_save (XedDocument *doc,
*/ */
void void
xed_document_save_as (XedDocument *doc, xed_document_save_as (XedDocument *doc,
const gchar *uri, GFile *location,
const XedEncoding *encoding, const XedEncoding *encoding,
XedDocumentSaveFlags flags) XedDocumentSaveFlags flags)
{ {
g_return_if_fail (XED_IS_DOCUMENT (doc)); g_return_if_fail (XED_IS_DOCUMENT (doc));
g_return_if_fail (uri != NULL); g_return_if_fail (G_IS_FILE (location));
g_return_if_fail (encoding != NULL); g_return_if_fail (encoding != NULL);
/* priv->mtime refers to the the old uri (if any). Thus, it should be /* priv->mtime refers to the the old location (if any). Thus, it should be
* ignored when saving as. */ * ignored when saving as. */
g_signal_emit (doc, document_signals[SAVE], 0, uri, encoding, flags | XED_DOCUMENT_SAVE_IGNORE_MTIME); g_signal_emit (doc, document_signals[SAVE], 0, location, encoding, flags | XED_DOCUMENT_SAVE_IGNORE_MTIME);
}
gboolean
xed_document_insert_file (XedDocument *doc,
GtkTextIter *iter,
const gchar *uri,
const XedEncoding *encoding)
{
g_return_val_if_fail (XED_IS_DOCUMENT (doc), FALSE);
g_return_val_if_fail (iter != NULL, FALSE);
g_return_val_if_fail (gtk_text_iter_get_buffer (iter) == GTK_TEXT_BUFFER (doc), FALSE);
/* TODO */
return FALSE;
} }
gboolean gboolean
@ -1612,7 +1599,7 @@ xed_document_is_untouched (XedDocument *doc)
{ {
g_return_val_if_fail (XED_IS_DOCUMENT (doc), TRUE); g_return_val_if_fail (XED_IS_DOCUMENT (doc), TRUE);
return (doc->priv->uri == NULL) && (!gtk_text_buffer_get_modified (GTK_TEXT_BUFFER (doc))); return (doc->priv->location == NULL) && (!gtk_text_buffer_get_modified (GTK_TEXT_BUFFER (doc)));
} }
gboolean gboolean
@ -1620,7 +1607,7 @@ xed_document_is_untitled (XedDocument *doc)
{ {
g_return_val_if_fail (XED_IS_DOCUMENT (doc), TRUE); g_return_val_if_fail (XED_IS_DOCUMENT (doc), TRUE);
return (doc->priv->uri == NULL); return (doc->priv->location == NULL);
} }
gboolean gboolean
@ -1628,12 +1615,12 @@ xed_document_is_local (XedDocument *doc)
{ {
g_return_val_if_fail (XED_IS_DOCUMENT (doc), FALSE); g_return_val_if_fail (XED_IS_DOCUMENT (doc), FALSE);
if (doc->priv->uri == NULL) if (doc->priv->location == NULL)
{ {
return FALSE; return FALSE;
} }
return xed_utils_uri_has_file_scheme (doc->priv->uri); return xed_utils_location_has_file_scheme (doc->priv->location);
} }
gboolean gboolean
@ -1641,7 +1628,8 @@ xed_document_get_deleted (XedDocument *doc)
{ {
g_return_val_if_fail (XED_IS_DOCUMENT (doc), FALSE); g_return_val_if_fail (XED_IS_DOCUMENT (doc), FALSE);
return doc->priv->uri && !xed_utils_uri_exists (doc->priv->uri); /* This is done sync, maybe we should do it async? */
return doc->priv->location && !xed_utils_location_exists (doc->priv->location);
} }
/* /*
@ -2592,14 +2580,14 @@ gchar *
xed_document_get_metadata (XedDocument *doc, xed_document_get_metadata (XedDocument *doc,
const gchar *key) const gchar *key)
{ {
gchar *value = NULL; gchar *uri;
g_return_val_if_fail (XED_IS_DOCUMENT (doc), NULL); g_return_val_if_fail (XED_IS_DOCUMENT (doc), NULL);
g_return_val_if_fail (key != NULL, NULL); g_return_val_if_fail (key != NULL, NULL);
if (!xed_document_is_untitled (doc)) if (!xed_document_is_untitled (doc))
{ {
value = xed_metadata_manager_get (doc->priv->uri, key); value = xed_metadata_manager_get (doc->priv->location, key);
} }
return value; return value;
@ -2629,8 +2617,11 @@ xed_document_set_metadata (XedDocument *doc,
{ {
value = va_arg (var_args, const gchar *); value = va_arg (var_args, const gchar *);
if (doc->priv->location != NULL)
{
xed_metadata_manager_set (doc->priv->uri, key, value); xed_metadata_manager_set (doc->priv->uri, key, value);
} }
}
va_end (var_args); va_end (var_args);
} }

View File

@ -117,7 +117,7 @@ struct _XedDocumentClass
/* Document load */ /* Document load */
void (* load) (XedDocument *document, void (* load) (XedDocument *document,
const gchar *uri, GFile *location,
const XedEncoding *encoding, const XedEncoding *encoding,
gint line_pos, gint line_pos,
gboolean create); gboolean create);
@ -131,7 +131,7 @@ struct _XedDocumentClass
/* Document save */ /* Document save */
void (* save) (XedDocument *document, void (* save) (XedDocument *document,
const gchar *uri, GFile *location,
const XedEncoding *encoding, const XedEncoding *encoding,
XedDocumentSaveFlags flags); XedDocumentSaveFlags flags);
@ -169,9 +169,8 @@ XedDocument *xed_document_new (void);
GFile *xed_document_get_location (XedDocument *doc); GFile *xed_document_get_location (XedDocument *doc);
gchar *xed_document_get_uri (XedDocument *doc); void xed_document_set_location (XedDocument *doc,
void xed_document_set_uri (XedDocument *doc, GFile *location);
const gchar *uri);
gchar *xed_document_get_uri_for_display gchar *xed_document_get_uri_for_display
(XedDocument *doc); (XedDocument *doc);
@ -194,23 +193,18 @@ gchar *xed_document_get_mime_type (XedDocument *doc);
gboolean xed_document_get_readonly (XedDocument *doc); gboolean xed_document_get_readonly (XedDocument *doc);
void xed_document_load (XedDocument *doc, void xed_document_load (XedDocument *doc,
const gchar *uri, GFile *location,
const XedEncoding *encoding, const XedEncoding *encoding,
gint line_pos, gint line_pos,
gboolean create); gboolean create);
gboolean xed_document_insert_file (XedDocument *doc,
GtkTextIter *iter,
const gchar *uri,
const XedEncoding *encoding);
gboolean xed_document_load_cancel (XedDocument *doc); gboolean xed_document_load_cancel (XedDocument *doc);
void xed_document_save (XedDocument *doc, void xed_document_save (XedDocument *doc,
XedDocumentSaveFlags flags); XedDocumentSaveFlags flags);
void xed_document_save_as (XedDocument *doc, void xed_document_save_as (XedDocument *doc,
const gchar *uri, GFile *location,
const XedEncoding *encoding, const XedEncoding *encoding,
XedDocumentSaveFlags flags); XedDocumentSaveFlags flags);

View File

@ -1,708 +0,0 @@
/*
* xed-gio-document-loader.c
* This file is part of xed
*
* Copyright (C) 2005 - Paolo Maggi
* Copyright (C) 2007 - Paolo Maggi, Steve Frécinaux
* Copyright (C) 2008 - Jesse van den Kieboom
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xed Team, 2005-2008. See the AUTHORS file for a
* list of people on the xed Team.
* See the ChangeLog files for a list of changes.
*
* $Id$
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <glib/gi18n.h>
#include <glib/gstdio.h>
#include <gio/gio.h>
#include "xed-gio-document-loader.h"
#include "xed-document-output-stream.h"
#include "xed-smart-charset-converter.h"
#include "xed-prefs-manager.h"
#include "xed-debug.h"
#include "xed-utils.h"
#ifndef ENABLE_GVFS_METADATA
#include "xed-metadata-manager.h"
#endif
typedef struct
{
XedGioDocumentLoader *loader;
GCancellable *cancellable;
gssize read;
gboolean tried_mount;
} AsyncData;
#define READ_CHUNK_SIZE 8192
#define REMOTE_QUERY_ATTRIBUTES G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE "," \
G_FILE_ATTRIBUTE_STANDARD_TYPE "," \
G_FILE_ATTRIBUTE_TIME_MODIFIED "," \
G_FILE_ATTRIBUTE_STANDARD_SIZE "," \
G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE "," \
XED_METADATA_ATTRIBUTE_ENCODING
#define XED_GIO_DOCUMENT_LOADER_GET_PRIVATE(object) \
(G_TYPE_INSTANCE_GET_PRIVATE ((object), \
XED_TYPE_GIO_DOCUMENT_LOADER, \
XedGioDocumentLoaderPrivate))
static void xed_gio_document_loader_load (XedDocumentLoader *loader);
static gboolean xed_gio_document_loader_cancel (XedDocumentLoader *loader);
static goffset xed_gio_document_loader_get_bytes_read (XedDocumentLoader *loader);
static void open_async_read (AsyncData *async);
struct _XedGioDocumentLoaderPrivate
{
/* Info on the current file */
GFile *gfile;
goffset bytes_read;
/* Handle for remote files */
GCancellable *cancellable;
GInputStream *stream;
GOutputStream *output;
XedSmartCharsetConverter *converter;
gchar buffer[READ_CHUNK_SIZE];
GError *error;
};
G_DEFINE_TYPE(XedGioDocumentLoader, xed_gio_document_loader, XED_TYPE_DOCUMENT_LOADER)
static void
xed_gio_document_loader_dispose (GObject *object)
{
XedGioDocumentLoaderPrivate *priv;
priv = XED_GIO_DOCUMENT_LOADER (object)->priv;
if (priv->cancellable != NULL)
{
g_cancellable_cancel (priv->cancellable);
g_object_unref (priv->cancellable);
priv->cancellable = NULL;
}
if (priv->stream != NULL)
{
g_object_unref (priv->stream);
priv->stream = NULL;
}
if (priv->output != NULL)
{
g_object_unref (priv->output);
priv->output = NULL;
}
if (priv->converter != NULL)
{
g_object_unref (priv->converter);
priv->converter = NULL;
}
if (priv->gfile != NULL)
{
g_object_unref (priv->gfile);
priv->gfile = NULL;
}
if (priv->error != NULL)
{
g_error_free (priv->error);
priv->error = NULL;
}
G_OBJECT_CLASS (xed_gio_document_loader_parent_class)->dispose (object);
}
static void
xed_gio_document_loader_class_init (XedGioDocumentLoaderClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
XedDocumentLoaderClass *loader_class = XED_DOCUMENT_LOADER_CLASS (klass);
object_class->dispose = xed_gio_document_loader_dispose;
loader_class->load = xed_gio_document_loader_load;
loader_class->cancel = xed_gio_document_loader_cancel;
loader_class->get_bytes_read = xed_gio_document_loader_get_bytes_read;
g_type_class_add_private (object_class, sizeof(XedGioDocumentLoaderPrivate));
}
static void
xed_gio_document_loader_init (XedGioDocumentLoader *gvloader)
{
gvloader->priv = XED_GIO_DOCUMENT_LOADER_GET_PRIVATE (gvloader);
gvloader->priv->converter = NULL;
gvloader->priv->error = NULL;
}
static AsyncData *
async_data_new (XedGioDocumentLoader *gvloader)
{
AsyncData *async;
async = g_slice_new (AsyncData);
async->loader = gvloader;
async->cancellable = g_object_ref (gvloader->priv->cancellable);
async->tried_mount = FALSE;
return async;
}
static void
async_data_free (AsyncData *async)
{
g_object_unref (async->cancellable);
g_slice_free (AsyncData, async);
}
static const XedEncoding *
get_metadata_encoding (XedDocumentLoader *loader)
{
const XedEncoding *enc = NULL;
#ifndef ENABLE_GVFS_METADATA
gchar *charset;
const gchar *uri;
uri = xed_document_loader_get_uri (loader);
charset = xed_metadata_manager_get (uri, "encoding");
if (charset == NULL)
return NULL;
enc = xed_encoding_get_from_charset (charset);
g_free (charset);
#else
GFileInfo *info;
info = xed_document_loader_get_info (loader);
/* check if the encoding was set in the metadata */
if (g_file_info_has_attribute (info, XED_METADATA_ATTRIBUTE_ENCODING))
{
const gchar *charset;
charset = g_file_info_get_attribute_string (info,
XED_METADATA_ATTRIBUTE_ENCODING);
if (charset == NULL)
return NULL;
enc = xed_encoding_get_from_charset (charset);
}
#endif
return enc;
}
static void
remote_load_completed_or_failed (XedGioDocumentLoader *loader, AsyncData *async)
{
xed_document_loader_loading (XED_DOCUMENT_LOADER (loader),
TRUE,
loader->priv->error);
if (async)
async_data_free (async);
}
static void
async_failed (AsyncData *async, GError *error)
{
g_propagate_error (&async->loader->priv->error, error);
remote_load_completed_or_failed (async->loader, async);
}
static void
close_input_stream_ready_cb (GInputStream *stream,
GAsyncResult *res,
AsyncData *async)
{
GError *error = NULL;
xed_debug (DEBUG_LOADER);
/* check cancelled state manually */
if (g_cancellable_is_cancelled (async->cancellable))
{
async_data_free (async);
return;
}
xed_debug_message (DEBUG_SAVER, "Finished closing input stream");
if (!g_input_stream_close_finish (stream, res, &error))
{
xed_debug_message (DEBUG_SAVER, "Closing input stream error: %s", error->message);
async_failed (async, error);
return;
}
xed_debug_message (DEBUG_SAVER, "Close output stream");
if (!g_output_stream_close (async->loader->priv->output,
async->cancellable, &error))
{
async_failed (async, error);
return;
}
remote_load_completed_or_failed (async->loader, async);
}
static void
write_complete (AsyncData *async)
{
if (async->loader->priv->stream)
g_input_stream_close_async (G_INPUT_STREAM (async->loader->priv->stream),
G_PRIORITY_HIGH,
async->cancellable,
(GAsyncReadyCallback)close_input_stream_ready_cb,
async);
}
/* prototype, because they call each other... isn't C lovely */
static void read_file_chunk (AsyncData *async);
static void
write_file_chunk (AsyncData *async)
{
XedGioDocumentLoader *gvloader;
gssize bytes_written;
GError *error = NULL;
gvloader = async->loader;
/* we use sync methods on doc stream since it is in memory. Using async
would be racy and we can endup with invalidated iters */
bytes_written = g_output_stream_write (G_OUTPUT_STREAM (gvloader->priv->output),
gvloader->priv->buffer,
async->read,
async->cancellable,
&error);
xed_debug_message (DEBUG_SAVER, "Written: %" G_GSSIZE_FORMAT, bytes_written);
if (bytes_written == -1)
{
xed_debug_message (DEBUG_SAVER, "Write error: %s", error->message);
async_failed (async, error);
return;
}
/* note that this signal blocks the read... check if it isn't
* a performance problem
*/
xed_document_loader_loading (XED_DOCUMENT_LOADER (gvloader),
FALSE,
NULL);
read_file_chunk (async);
}
static void
async_read_cb (GInputStream *stream,
GAsyncResult *res,
AsyncData *async)
{
xed_debug (DEBUG_LOADER);
XedGioDocumentLoader *gvloader;
GError *error = NULL;
xed_debug (DEBUG_LOADER);
/* manually check cancelled state */
if (g_cancellable_is_cancelled (async->cancellable))
{
async_data_free (async);
return;
}
gvloader = async->loader;
async->read = g_input_stream_read_finish (stream, res, &error);
/* error occurred */
if (async->read == -1)
{
async_failed (async, error);
return;
}
/* Check for the extremely unlikely case where the file size overflows. */
if (gvloader->priv->bytes_read + async->read < gvloader->priv->bytes_read)
{
g_set_error (&gvloader->priv->error,
XED_DOCUMENT_ERROR,
XED_DOCUMENT_ERROR_TOO_BIG,
"File too big");
async_failed (async, gvloader->priv->error);
return;
}
/* Bump the size. */
gvloader->priv->bytes_read += async->read;
/* end of the file, we are done! */
if (async->read == 0)
{
XedDocumentLoader *loader;
loader = XED_DOCUMENT_LOADER (gvloader);
g_output_stream_flush (gvloader->priv->output,
NULL,
&gvloader->priv->error);
loader->auto_detected_encoding =
xed_smart_charset_converter_get_guessed (gvloader->priv->converter);
loader->auto_detected_newline_type =
xed_document_output_stream_detect_newline_type (XED_DOCUMENT_OUTPUT_STREAM (gvloader->priv->output));
/* Check if we needed some fallback char, if so, check if there was
a previous error and if not set a fallback used error */
/* FIXME Uncomment this when we want to manage conversion fallback */
/*if ((xed_smart_charset_converter_get_num_fallbacks (gvloader->priv->converter) != 0) &&
gvloader->priv->error == NULL)
{
g_set_error_literal (&gvloader->priv->error,
XED_DOCUMENT_ERROR,
XED_DOCUMENT_ERROR_CONVERSION_FALLBACK,
"There was a conversion error and it was "
"needed to use a fallback char");
}*/
write_complete (async);
return;
}
write_file_chunk (async);
}
static void
read_file_chunk (AsyncData *async)
{
XedGioDocumentLoader *gvloader;
gvloader = async->loader;
g_input_stream_read_async (G_INPUT_STREAM (gvloader->priv->stream),
gvloader->priv->buffer,
READ_CHUNK_SIZE,
G_PRIORITY_HIGH,
async->cancellable,
(GAsyncReadyCallback) async_read_cb,
async);
}
static GSList *
get_candidate_encodings (XedGioDocumentLoader *gvloader)
{
const XedEncoding *metadata;
GSList *encodings = NULL;
encodings = xed_prefs_manager_get_auto_detected_encodings ();
metadata = get_metadata_encoding (XED_DOCUMENT_LOADER (gvloader));
if (metadata != NULL)
{
encodings = g_slist_prepend (encodings, (gpointer)metadata);
}
return encodings;
}
static void
finish_query_info (AsyncData *async)
{
XedGioDocumentLoader *gvloader;
XedDocumentLoader *loader;
GInputStream *conv_stream;
GFileInfo *info;
GSList *candidate_encodings;
gvloader = async->loader;
loader = XED_DOCUMENT_LOADER (gvloader);
info = loader->info;
/* if it's not a regular file, error out... */
if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_TYPE) &&
g_file_info_get_file_type (info) != G_FILE_TYPE_REGULAR)
{
g_set_error (&gvloader->priv->error,
G_IO_ERROR,
G_IO_ERROR_NOT_REGULAR_FILE,
"Not a regular file");
remote_load_completed_or_failed (gvloader, async);
return;
}
/* Get the candidate encodings */
if (loader->encoding == NULL)
{
candidate_encodings = get_candidate_encodings (gvloader);
}
else
{
candidate_encodings = g_slist_prepend (NULL, (gpointer) loader->encoding);
}
gvloader->priv->converter = xed_smart_charset_converter_new (candidate_encodings);
g_slist_free (candidate_encodings);
conv_stream = g_converter_input_stream_new (gvloader->priv->stream,
G_CONVERTER (gvloader->priv->converter));
g_object_unref (gvloader->priv->stream);
gvloader->priv->stream = conv_stream;
/* Output stream */
gvloader->priv->output = xed_document_output_stream_new (loader->document);
/* start reading */
read_file_chunk (async);
}
static void
query_info_cb (GFile *source,
GAsyncResult *res,
AsyncData *async)
{
XedGioDocumentLoader *gvloader;
GFileInfo *info;
GError *error = NULL;
xed_debug (DEBUG_LOADER);
/* manually check the cancelled state */
if (g_cancellable_is_cancelled (async->cancellable))
{
async_data_free (async);
return;
}
gvloader = async->loader;
/* finish the info query */
info = g_file_query_info_finish (gvloader->priv->gfile,
res,
&error);
if (info == NULL)
{
/* propagate the error and clean up */
async_failed (async, error);
return;
}
XED_DOCUMENT_LOADER (gvloader)->info = info;
finish_query_info (async);
}
static void
mount_ready_callback (GFile *file,
GAsyncResult *res,
AsyncData *async)
{
GError *error = NULL;
gboolean mounted;
xed_debug (DEBUG_LOADER);
/* manual check for cancelled state */
if (g_cancellable_is_cancelled (async->cancellable))
{
async_data_free (async);
return;
}
mounted = g_file_mount_enclosing_volume_finish (file, res, &error);
if (!mounted)
{
async_failed (async, error);
}
else
{
/* try again to open the file for reading */
open_async_read (async);
}
}
static void
recover_not_mounted (AsyncData *async)
{
XedDocument *doc;
GMountOperation *mount_operation;
xed_debug (DEBUG_LOADER);
doc = xed_document_loader_get_document (XED_DOCUMENT_LOADER (async->loader));
mount_operation = _xed_document_create_mount_operation (doc);
async->tried_mount = TRUE;
g_file_mount_enclosing_volume (async->loader->priv->gfile,
G_MOUNT_MOUNT_NONE,
mount_operation,
async->cancellable,
(GAsyncReadyCallback) mount_ready_callback,
async);
g_object_unref (mount_operation);
}
static void
async_read_ready_callback (GObject *source,
GAsyncResult *res,
AsyncData *async)
{
GError *error = NULL;
XedGioDocumentLoader *gvloader;
xed_debug (DEBUG_LOADER);
/* manual check for cancelled state */
if (g_cancellable_is_cancelled (async->cancellable))
{
async_data_free (async);
return;
}
gvloader = async->loader;
gvloader->priv->stream = G_INPUT_STREAM (g_file_read_finish (gvloader->priv->gfile,
res, &error));
if (!gvloader->priv->stream)
{
if (error->code == G_IO_ERROR_NOT_MOUNTED && !async->tried_mount)
{
recover_not_mounted (async);
g_error_free (error);
return;
}
/* Propagate error */
g_propagate_error (&gvloader->priv->error, error);
xed_document_loader_loading (XED_DOCUMENT_LOADER (gvloader),
TRUE,
gvloader->priv->error);
async_data_free (async);
return;
}
/* get the file info: note we cannot use
* g_file_input_stream_query_info_async since it is not able to get the
* content type etc, beside it is not supported by gvfs.
* Using the file instead of the stream is slightly racy, but for
* loading this is not too bad...
*/
g_file_query_info_async (gvloader->priv->gfile,
REMOTE_QUERY_ATTRIBUTES,
G_FILE_QUERY_INFO_NONE,
G_PRIORITY_HIGH,
async->cancellable,
(GAsyncReadyCallback) query_info_cb,
async);
}
static void
open_async_read (AsyncData *async)
{
g_file_read_async (async->loader->priv->gfile,
G_PRIORITY_HIGH,
async->cancellable,
(GAsyncReadyCallback) async_read_ready_callback,
async);
}
static void
xed_gio_document_loader_load (XedDocumentLoader *loader)
{
XedGioDocumentLoader *gvloader = XED_GIO_DOCUMENT_LOADER (loader);
AsyncData *async;
xed_debug (DEBUG_LOADER);
/* make sure no load operation is currently running */
g_return_if_fail (gvloader->priv->cancellable == NULL);
gvloader->priv->gfile = g_file_new_for_uri (loader->uri);
/* loading start */
xed_document_loader_loading (XED_DOCUMENT_LOADER (gvloader),
FALSE,
NULL);
gvloader->priv->cancellable = g_cancellable_new ();
async = async_data_new (gvloader);
open_async_read (async);
}
static goffset
xed_gio_document_loader_get_bytes_read (XedDocumentLoader *loader)
{
return XED_GIO_DOCUMENT_LOADER (loader)->priv->bytes_read;
}
static gboolean
xed_gio_document_loader_cancel (XedDocumentLoader *loader)
{
XedGioDocumentLoader *gvloader = XED_GIO_DOCUMENT_LOADER (loader);
if (gvloader->priv->cancellable == NULL)
return FALSE;
g_cancellable_cancel (gvloader->priv->cancellable);
g_set_error (&gvloader->priv->error,
G_IO_ERROR,
G_IO_ERROR_CANCELLED,
"Operation cancelled");
remote_load_completed_or_failed (gvloader, NULL);
return TRUE;
}

View File

@ -1,79 +0,0 @@
/*
* xed-gio-document-loader.h
* This file is part of xed
*
* Copyright (C) 2005 - Paolo Maggi
* Copyright (C) 2007 - Paolo Maggi, Steve Frécinaux
* Copyright (C) 2008 - Jesse van den Kieboom
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xed Team, 2005-2008. See the AUTHORS file for a
* list of people on the xed Team.
* See the ChangeLog files for a list of changes.
*
* $Id$
*/
#ifndef __XED_GIO_DOCUMENT_LOADER_H__
#define __XED_GIO_DOCUMENT_LOADER_H__
#include <xed/xed-document.h>
#include "xed-document-loader.h"
G_BEGIN_DECLS
/*
* Type checking and casting macros
*/
#define XED_TYPE_GIO_DOCUMENT_LOADER (xed_gio_document_loader_get_type())
#define XED_GIO_DOCUMENT_LOADER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), XED_TYPE_GIO_DOCUMENT_LOADER, XedGioDocumentLoader))
#define XED_GIO_DOCUMENT_LOADER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), XED_TYPE_GIO_DOCUMENT_LOADER, XedGioDocumentLoaderClass))
#define XED_IS_GIO_DOCUMENT_LOADER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), XED_TYPE_GIO_DOCUMENT_LOADER))
#define XED_IS_GIO_DOCUMENT_LOADER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XED_TYPE_GIO_DOCUMENT_LOADER))
#define XED_GIO_DOCUMENT_LOADER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), XED_TYPE_GIO_DOCUMENT_LOADER, XedGioDocumentLoaderClass))
/* Private structure type */
typedef struct _XedGioDocumentLoaderPrivate XedGioDocumentLoaderPrivate;
/*
* Main object structure
*/
typedef struct _XedGioDocumentLoader XedGioDocumentLoader;
struct _XedGioDocumentLoader
{
XedDocumentLoader loader;
/*< private > */
XedGioDocumentLoaderPrivate *priv;
};
/*
* Class definition
*/
typedef XedDocumentLoaderClass XedGioDocumentLoaderClass;
/*
* Public methods
*/
GType xed_gio_document_loader_get_type (void) G_GNUC_CONST;
G_END_DECLS
#endif /* __XED_GIO_DOCUMENT_LOADER_H__ */

View File

@ -1,775 +0,0 @@
/*
* xed-gio-document-saver.c
* This file is part of xed
*
* Copyright (C) 2005-2006 - Paolo Borelli and Paolo Maggi
* Copyright (C) 2007 - Paolo Borelli, Paolo Maggi, Steve Frécinaux
* Copyright (C) 2008 - Jesse van den Kieboom
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xed Team, 2005-2006. See the AUTHORS file for a
* list of people on the xed Team.
* See the ChangeLog files for a list of changes.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <glib/gi18n.h>
#include <glib.h>
#include <gio/gio.h>
#include <string.h>
#include "xed-gio-document-saver.h"
#include "xed-document-input-stream.h"
#include "xed-debug.h"
#define WRITE_CHUNK_SIZE 8192
typedef struct
{
XedGioDocumentSaver *saver;
gchar buffer[WRITE_CHUNK_SIZE];
GCancellable *cancellable;
gboolean tried_mount;
gssize written;
gssize read;
GError *error;
} AsyncData;
#define REMOTE_QUERY_ATTRIBUTES G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE "," \
G_FILE_ATTRIBUTE_TIME_MODIFIED
#define XED_GIO_DOCUMENT_SAVER_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), \
XED_TYPE_GIO_DOCUMENT_SAVER, \
XedGioDocumentSaverPrivate))
static void xed_gio_document_saver_save (XedDocumentSaver *saver,
GTimeVal *old_mtime);
static goffset xed_gio_document_saver_get_file_size (XedDocumentSaver *saver);
static goffset xed_gio_document_saver_get_bytes_written (XedDocumentSaver *saver);
static void check_modified_async (AsyncData *async);
struct _XedGioDocumentSaverPrivate
{
GTimeVal old_mtime;
goffset size;
goffset bytes_written;
GFile *gfile;
GCancellable *cancellable;
GOutputStream *stream;
GInputStream *input;
GError *error;
};
G_DEFINE_TYPE(XedGioDocumentSaver, xed_gio_document_saver, XED_TYPE_DOCUMENT_SAVER)
static void
xed_gio_document_saver_dispose (GObject *object)
{
XedGioDocumentSaverPrivate *priv = XED_GIO_DOCUMENT_SAVER (object)->priv;
if (priv->cancellable != NULL)
{
g_cancellable_cancel (priv->cancellable);
g_object_unref (priv->cancellable);
priv->cancellable = NULL;
}
if (priv->gfile != NULL)
{
g_object_unref (priv->gfile);
priv->gfile = NULL;
}
if (priv->error != NULL)
{
g_error_free (priv->error);
priv->error = NULL;
}
if (priv->stream != NULL)
{
g_object_unref (priv->stream);
priv->stream = NULL;
}
if (priv->input != NULL)
{
g_object_unref (priv->input);
priv->input = NULL;
}
G_OBJECT_CLASS (xed_gio_document_saver_parent_class)->dispose (object);
}
static AsyncData *
async_data_new (XedGioDocumentSaver *gvsaver)
{
AsyncData *async;
async = g_slice_new (AsyncData);
async->saver = gvsaver;
async->cancellable = g_object_ref (gvsaver->priv->cancellable);
async->tried_mount = FALSE;
async->written = 0;
async->read = 0;
async->error = NULL;
return async;
}
static void
async_data_free (AsyncData *async)
{
g_object_unref (async->cancellable);
if (async->error)
{
g_error_free (async->error);
}
g_slice_free (AsyncData, async);
}
static void
xed_gio_document_saver_class_init (XedGioDocumentSaverClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
XedDocumentSaverClass *saver_class = XED_DOCUMENT_SAVER_CLASS (klass);
object_class->dispose = xed_gio_document_saver_dispose;
saver_class->save = xed_gio_document_saver_save;
saver_class->get_file_size = xed_gio_document_saver_get_file_size;
saver_class->get_bytes_written = xed_gio_document_saver_get_bytes_written;
g_type_class_add_private (object_class, sizeof(XedGioDocumentSaverPrivate));
}
static void
xed_gio_document_saver_init (XedGioDocumentSaver *gvsaver)
{
gvsaver->priv = XED_GIO_DOCUMENT_SAVER_GET_PRIVATE (gvsaver);
gvsaver->priv->cancellable = g_cancellable_new ();
gvsaver->priv->error = NULL;
}
static void
remote_save_completed_or_failed (XedGioDocumentSaver *gvsaver,
AsyncData *async)
{
xed_document_saver_saving (XED_DOCUMENT_SAVER (gvsaver),
TRUE,
gvsaver->priv->error);
if (async)
async_data_free (async);
}
static void
async_failed (AsyncData *async,
GError *error)
{
g_propagate_error (&async->saver->priv->error, error);
remote_save_completed_or_failed (async->saver, async);
}
/* BEGIN NOTE:
*
* This fixes an issue in GOutputStream that applies the atomic replace
* save strategy. The stream moves the written file to the original file
* when the stream is closed. However, there is no way currently to tell
* the stream that the save should be aborted (there could be a
* conversion error). The patch explicitly closes the output stream
* in all these cases with a GCancellable in the cancelled state, causing
* the output stream to close, but not move the file. This makes use
* of an implementation detail in the local gio file stream and should be
* properly fixed by adding the appropriate API in gio. Until then, at least
* we prevent data corruption for now.
*
* Relevant bug reports:
*
* Bug 615110 - write file ignore encoding errors (xed)
* https://bugzilla.gnome.org/show_bug.cgi?id=615110
*
* Bug 602412 - g_file_replace does not restore original file when there is
* errors while writing (glib/gio)
* https://bugzilla.gnome.org/show_bug.cgi?id=602412
*/
static void
cancel_output_stream_ready_cb (GOutputStream *stream,
GAsyncResult *result,
AsyncData *async)
{
GError *error;
g_output_stream_close_finish (stream, result, NULL);
/* check cancelled state manually */
if (g_cancellable_is_cancelled (async->cancellable) || async->error == NULL)
{
async_data_free (async);
return;
}
error = async->error;
async->error = NULL;
async_failed (async, error);
}
static void
cancel_output_stream (AsyncData *async)
{
GCancellable *cancellable;
xed_debug_message (DEBUG_SAVER, "Cancel output stream");
cancellable = g_cancellable_new ();
g_cancellable_cancel (cancellable);
g_output_stream_close_async (async->saver->priv->stream,
G_PRIORITY_HIGH,
cancellable,
(GAsyncReadyCallback)cancel_output_stream_ready_cb,
async);
g_object_unref (cancellable);
}
static void
cancel_output_stream_and_fail (AsyncData *async,
GError *error)
{
xed_debug_message (DEBUG_SAVER, "Cancel output stream and fail");
g_propagate_error (&async->error, error);
cancel_output_stream (async);
}
/*
* END NOTE
*/
static void
remote_get_info_cb (GFile *source,
GAsyncResult *res,
AsyncData *async)
{
XedGioDocumentSaver *saver;
GFileInfo *info;
GError *error = NULL;
xed_debug (DEBUG_SAVER);
/* check cancelled state manually */
if (g_cancellable_is_cancelled (async->cancellable))
{
async_data_free (async);
return;
}
saver = async->saver;
xed_debug_message (DEBUG_SAVER, "Finished query info on file");
info = g_file_query_info_finish (source, res, &error);
if (info != NULL)
{
if (XED_DOCUMENT_SAVER (saver)->info != NULL)
g_object_unref (XED_DOCUMENT_SAVER (saver)->info);
XED_DOCUMENT_SAVER (saver)->info = info;
}
else
{
xed_debug_message (DEBUG_SAVER, "Query info failed: %s", error->message);
g_propagate_error (&saver->priv->error, error);
}
remote_save_completed_or_failed (saver, async);
}
static void
close_async_ready_get_info_cb (GOutputStream *stream,
GAsyncResult *res,
AsyncData *async)
{
GError *error = NULL;
xed_debug (DEBUG_SAVER);
/* check cancelled state manually */
if (g_cancellable_is_cancelled (async->cancellable))
{
async_data_free (async);
return;
}
xed_debug_message (DEBUG_SAVER, "Finished closing stream");
if (!g_output_stream_close_finish (stream, res, &error))
{
xed_debug_message (DEBUG_SAVER, "Closing stream error: %s", error->message);
async_failed (async, error);
return;
}
/* get the file info: note we cannot use
* g_file_output_stream_query_info_async since it is not able to get the
* content type etc, beside it is not supported by gvfs.
* I'm not sure this is actually necessary, can't we just use
* g_content_type_guess (since we have the file name and the data)
*/
xed_debug_message (DEBUG_SAVER, "Query info on file");
g_file_query_info_async (async->saver->priv->gfile,
REMOTE_QUERY_ATTRIBUTES,
G_FILE_QUERY_INFO_NONE,
G_PRIORITY_HIGH,
async->cancellable,
(GAsyncReadyCallback) remote_get_info_cb,
async);
}
static void
write_complete (AsyncData *async)
{
GError *error = NULL;
/* first we close the input stream */
xed_debug_message (DEBUG_SAVER, "Close input stream");
if (!g_input_stream_close (async->saver->priv->input,
async->cancellable, &error))
{
xed_debug_message (DEBUG_SAVER, "Closing input stream error: %s", error->message);
cancel_output_stream_and_fail (async, error);
return;
}
/* now we close the output stream */
xed_debug_message (DEBUG_SAVER, "Close output stream");
g_output_stream_close_async (async->saver->priv->stream,
G_PRIORITY_HIGH,
async->cancellable,
(GAsyncReadyCallback)close_async_ready_get_info_cb,
async);
}
/* prototype, because they call each other... isn't C lovely */
static void read_file_chunk (AsyncData *async);
static void write_file_chunk (AsyncData *async);
static void
async_write_cb (GOutputStream *stream,
GAsyncResult *res,
AsyncData *async)
{
XedGioDocumentSaver *gvsaver;
gssize bytes_written;
GError *error = NULL;
xed_debug (DEBUG_SAVER);
/* Check cancelled state manually */
if (g_cancellable_is_cancelled (async->cancellable))
{
cancel_output_stream (async);
return;
}
bytes_written = g_output_stream_write_finish (stream, res, &error);
xed_debug_message (DEBUG_SAVER, "Written: %" G_GSSIZE_FORMAT, bytes_written);
if (bytes_written == -1)
{
xed_debug_message (DEBUG_SAVER, "Write error: %s", error->message);
cancel_output_stream_and_fail (async, error);
return;
}
gvsaver = async->saver;
async->written += bytes_written;
/* write again */
if (async->written != async->read)
{
write_file_chunk (async);
return;
}
/* note that this signal blocks the write... check if it isn't
* a performance problem
*/
xed_document_saver_saving (XED_DOCUMENT_SAVER (gvsaver),
FALSE,
NULL);
read_file_chunk (async);
}
static void
write_file_chunk (AsyncData *async)
{
XedGioDocumentSaver *gvsaver;
xed_debug (DEBUG_SAVER);
gvsaver = async->saver;
g_output_stream_write_async (G_OUTPUT_STREAM (gvsaver->priv->stream),
async->buffer + async->written,
async->read - async->written,
G_PRIORITY_HIGH,
async->cancellable,
(GAsyncReadyCallback) async_write_cb,
async);
}
static void
read_file_chunk (AsyncData *async)
{
XedGioDocumentSaver *gvsaver;
XedDocumentInputStream *dstream;
GError *error = NULL;
xed_debug (DEBUG_SAVER);
gvsaver = async->saver;
async->written = 0;
/* we use sync methods on doc stream since it is in memory. Using async
would be racy and we can endup with invalidated iters */
async->read = g_input_stream_read (gvsaver->priv->input,
async->buffer,
WRITE_CHUNK_SIZE,
async->cancellable,
&error);
if (error != NULL)
{
cancel_output_stream_and_fail (async, error);
return;
}
/* Check if we finished reading and writing */
if (async->read == 0)
{
write_complete (async);
return;
}
/* Get how many chars have been read */
dstream = XED_DOCUMENT_INPUT_STREAM (gvsaver->priv->input);
gvsaver->priv->bytes_written = xed_document_input_stream_tell (dstream);
write_file_chunk (async);
}
static void
async_replace_ready_callback (GFile *source,
GAsyncResult *res,
AsyncData *async)
{
XedGioDocumentSaver *gvsaver;
XedDocumentSaver *saver;
GCharsetConverter *converter;
GFileOutputStream *file_stream;
GError *error = NULL;
xed_debug (DEBUG_SAVER);
/* Check cancelled state manually */
if (g_cancellable_is_cancelled (async->cancellable))
{
async_data_free (async);
return;
}
gvsaver = async->saver;
saver = XED_DOCUMENT_SAVER (gvsaver);
file_stream = g_file_replace_finish (source, res, &error);
/* handle any error that might occur */
if (!file_stream)
{
xed_debug_message (DEBUG_SAVER, "Opening file failed: %s", error->message);
async_failed (async, error);
return;
}
/* FIXME: manage converter error? */
xed_debug_message (DEBUG_SAVER, "Encoding charset: %s",
xed_encoding_get_charset (saver->encoding));
if (saver->encoding != xed_encoding_get_utf8 ())
{
converter = g_charset_converter_new (xed_encoding_get_charset (saver->encoding),
"UTF-8",
NULL);
gvsaver->priv->stream = g_converter_output_stream_new (G_OUTPUT_STREAM (file_stream),
G_CONVERTER (converter));
g_object_unref (file_stream);
g_object_unref (converter);
}
else
{
gvsaver->priv->stream = G_OUTPUT_STREAM (file_stream);
}
gvsaver->priv->input = xed_document_input_stream_new (GTK_TEXT_BUFFER (saver->document),
saver->newline_type);
gvsaver->priv->size = xed_document_input_stream_get_total_size (XED_DOCUMENT_INPUT_STREAM (gvsaver->priv->input));
read_file_chunk (async);
}
static void
begin_write (AsyncData *async)
{
XedGioDocumentSaver *gvsaver;
XedDocumentSaver *saver;
gboolean backup;
xed_debug_message (DEBUG_SAVER, "Start replacing file contents");
/* For remote files we simply use g_file_replace_async. There is no
* backup as of yet
*/
gvsaver = async->saver;
saver = XED_DOCUMENT_SAVER (gvsaver);
/* Do not make backups for remote files so they do not clutter remote systems */
backup = (saver->keep_backup && xed_document_is_local (saver->document));
xed_debug_message (DEBUG_SAVER, "File contents size: %" G_GINT64_FORMAT, gvsaver->priv->size);
xed_debug_message (DEBUG_SAVER, "Calling replace_async");
xed_debug_message (DEBUG_SAVER, backup ? "Keep backup" : "Discard backup");
g_file_replace_async (gvsaver->priv->gfile,
NULL,
backup,
G_FILE_CREATE_NONE,
G_PRIORITY_HIGH,
async->cancellable,
(GAsyncReadyCallback) async_replace_ready_callback,
async);
}
static void
mount_ready_callback (GFile *file,
GAsyncResult *res,
AsyncData *async)
{
GError *error = NULL;
gboolean mounted;
xed_debug (DEBUG_SAVER);
/* manual check for cancelled state */
if (g_cancellable_is_cancelled (async->cancellable))
{
async_data_free (async);
return;
}
mounted = g_file_mount_enclosing_volume_finish (file, res, &error);
if (!mounted)
{
async_failed (async, error);
}
else
{
/* try again to get the modified state */
check_modified_async (async);
}
}
static void
recover_not_mounted (AsyncData *async)
{
XedDocument *doc;
GMountOperation *mount_operation;
xed_debug (DEBUG_LOADER);
doc = xed_document_saver_get_document (XED_DOCUMENT_SAVER (async->saver));
mount_operation = _xed_document_create_mount_operation (doc);
async->tried_mount = TRUE;
g_file_mount_enclosing_volume (async->saver->priv->gfile,
G_MOUNT_MOUNT_NONE,
mount_operation,
async->cancellable,
(GAsyncReadyCallback) mount_ready_callback,
async);
g_object_unref (mount_operation);
}
static void
check_modification_callback (GFile *source,
GAsyncResult *res,
AsyncData *async)
{
XedGioDocumentSaver *gvsaver;
GError *error = NULL;
GFileInfo *info;
xed_debug (DEBUG_SAVER);
/* manually check cancelled state */
if (g_cancellable_is_cancelled (async->cancellable))
{
async_data_free (async);
return;
}
gvsaver = async->saver;
info = g_file_query_info_finish (source, res, &error);
if (info == NULL)
{
if (error->code == G_IO_ERROR_NOT_MOUNTED && !async->tried_mount)
{
recover_not_mounted (async);
g_error_free (error);
return;
}
/* it's perfectly fine if the file doesn't exist yet */
if (error->code != G_IO_ERROR_NOT_FOUND)
{
xed_debug_message (DEBUG_SAVER, "Error getting modification: %s", error->message);
async_failed (async, error);
return;
}
}
/* check if the mtime is > what we know about it (if we have it) */
if (info != NULL && g_file_info_has_attribute (info,
G_FILE_ATTRIBUTE_TIME_MODIFIED))
{
GTimeVal mtime;
GTimeVal old_mtime;
g_file_info_get_modification_time (info, &mtime);
old_mtime = gvsaver->priv->old_mtime;
if ((old_mtime.tv_sec > 0 || old_mtime.tv_usec > 0) &&
(mtime.tv_sec != old_mtime.tv_sec || mtime.tv_usec != old_mtime.tv_usec) &&
(XED_DOCUMENT_SAVER (gvsaver)->flags & XED_DOCUMENT_SAVE_IGNORE_MTIME) == 0)
{
xed_debug_message (DEBUG_SAVER, "File is externally modified");
g_set_error (&gvsaver->priv->error,
XED_DOCUMENT_ERROR,
XED_DOCUMENT_ERROR_EXTERNALLY_MODIFIED,
"Externally modified");
remote_save_completed_or_failed (gvsaver, async);
g_object_unref (info);
return;
}
}
if (info != NULL)
g_object_unref (info);
/* modification check passed, start write */
begin_write (async);
}
static void
check_modified_async (AsyncData *async)
{
xed_debug_message (DEBUG_SAVER, "Check externally modified");
g_file_query_info_async (async->saver->priv->gfile,
G_FILE_ATTRIBUTE_TIME_MODIFIED,
G_FILE_QUERY_INFO_NONE,
G_PRIORITY_HIGH,
async->cancellable,
(GAsyncReadyCallback) check_modification_callback,
async);
}
static gboolean
save_remote_file_real (XedGioDocumentSaver *gvsaver)
{
AsyncData *async;
xed_debug_message (DEBUG_SAVER, "Starting gio save");
/* First find out if the file is modified externally. This requires
* a stat, but I don't think we can do this any other way
*/
async = async_data_new (gvsaver);
check_modified_async (async);
/* return false to stop timeout */
return FALSE;
}
static void
xed_gio_document_saver_save (XedDocumentSaver *saver,
GTimeVal *old_mtime)
{
XedGioDocumentSaver *gvsaver = XED_GIO_DOCUMENT_SAVER (saver);
gvsaver->priv->old_mtime = *old_mtime;
gvsaver->priv->gfile = g_file_new_for_uri (saver->uri);
/* saving start */
xed_document_saver_saving (saver, FALSE, NULL);
g_timeout_add_full (G_PRIORITY_HIGH,
0,
(GSourceFunc) save_remote_file_real,
gvsaver,
NULL);
}
static goffset
xed_gio_document_saver_get_file_size (XedDocumentSaver *saver)
{
return XED_GIO_DOCUMENT_SAVER (saver)->priv->size;
}
static goffset
xed_gio_document_saver_get_bytes_written (XedDocumentSaver *saver)
{
return XED_GIO_DOCUMENT_SAVER (saver)->priv->bytes_written;
}

View File

@ -1,76 +0,0 @@
/*
* xed-gio-document-saver.h
* This file is part of xed
*
* Copyright (C) 2005 - Paolo Maggi
* Copyrhing (C) 2007 - Paolo Maggi, Steve Frécinaux
* Copyright (C) 2008 - Jesse van den Kieboom
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xed Team, 2005-2007. See the AUTHORS file for a
* list of people on the xed Team.
* See the ChangeLog files for a list of changes.
*/
#ifndef __XED_GIO_DOCUMENT_SAVER_H__
#define __XED_GIO_DOCUMENT_SAVER_H__
#include <xed/xed-document-saver.h>
G_BEGIN_DECLS
/*
* Type checking and casting macros
*/
#define XED_TYPE_GIO_DOCUMENT_SAVER (xed_gio_document_saver_get_type())
#define XED_GIO_DOCUMENT_SAVER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), XED_TYPE_GIO_DOCUMENT_SAVER, XedGioDocumentSaver))
#define XED_GIO_DOCUMENT_SAVER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), XED_TYPE_GIO_DOCUMENT_SAVER, XedGioDocumentSaverClass))
#define XED_IS_GIO_DOCUMENT_SAVER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), XED_TYPE_GIO_DOCUMENT_SAVER))
#define XED_IS_GIO_DOCUMENT_SAVER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XED_TYPE_GIO_DOCUMENT_SAVER))
#define XED_GIO_DOCUMENT_SAVER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), XED_TYPE_GIO_DOCUMENT_SAVER, XedGioDocumentSaverClass))
/* Private structure type */
typedef struct _XedGioDocumentSaverPrivate XedGioDocumentSaverPrivate;
/*
* Main object structure
*/
typedef struct _XedGioDocumentSaver XedGioDocumentSaver;
struct _XedGioDocumentSaver
{
XedDocumentSaver saver;
/*< private > */
XedGioDocumentSaverPrivate *priv;
};
/*
* Class definition
*/
typedef XedDocumentSaverClass XedGioDocumentSaverClass;
/*
* Public methods
*/
GType xed_gio_document_saver_get_type (void) G_GNUC_CONST;
G_END_DECLS
#endif /* __XED_GIO_DOCUMENT_SAVER_H__ */

View File

@ -180,7 +180,7 @@ static gboolean
parse_gio_error (gint code, parse_gio_error (gint code,
gchar **error_message, gchar **error_message,
gchar **message_details, gchar **message_details,
const gchar *uri, GFile *location,
const gchar *uri_for_display) const gchar *uri_for_display)
{ {
gboolean ret = TRUE; gboolean ret = TRUE;
@ -198,7 +198,7 @@ parse_gio_error (gint code,
gchar *scheme_string; gchar *scheme_string;
gchar *scheme_markup; gchar *scheme_markup;
scheme_string = g_uri_parse_scheme (uri); scheme_string = g_file_get_uri_scheme (location);
if ((scheme_string != NULL) && g_utf8_validate (scheme_string, -1, NULL)) if ((scheme_string != NULL) && g_utf8_validate (scheme_string, -1, NULL))
{ {
@ -240,8 +240,11 @@ parse_gio_error (gint code,
*/ */
{ {
gchar *hn = NULL; gchar *hn = NULL;
gchar *uri;
if (xed_utils_decode_uri (uri, NULL, NULL, &hn, NULL, NULL)) uri = g_file_get_uri (location);
if (uri && xed_utils_decode_uri (uri, NULL, NULL, &hn, NULL, NULL))
{ {
if (hn != NULL) if (hn != NULL)
{ {
@ -264,6 +267,8 @@ parse_gio_error (gint code,
} }
} }
g_free (uri);
if (!*message_details) if (!*message_details)
{ {
/* use the same string as INVALID_HOST */ /* use the same string as INVALID_HOST */
@ -291,7 +296,7 @@ static gboolean
parse_xed_error (gint code, parse_xed_error (gint code,
gchar **error_message, gchar **error_message,
gchar **message_details, gchar **message_details,
const gchar *uri, GFile *location,
const gchar *uri_for_display) const gchar *uri_for_display)
{ {
gboolean ret = TRUE; gboolean ret = TRUE;
@ -313,18 +318,18 @@ static void
parse_error (const GError *error, parse_error (const GError *error,
gchar **error_message, gchar **error_message,
gchar **message_details, gchar **message_details,
const gchar *uri, GFile *location,
const gchar *uri_for_display) const gchar *uri_for_display)
{ {
gboolean ret = FALSE; gboolean ret = FALSE;
if (error->domain == G_IO_ERROR) if (error->domain == G_IO_ERROR)
{ {
ret = parse_gio_error (error->code, error_message, message_details, uri, uri_for_display); ret = parse_gio_error (error->code, error_message, message_details, location, uri_for_display);
} }
else if (error->domain == XED_DOCUMENT_ERROR) else if (error->domain == XED_DOCUMENT_ERROR)
{ {
ret = parse_xed_error (error->code, error_message, message_details, uri, uri_for_display); ret = parse_xed_error (error->code, error_message, message_details, location, uri_for_display);
} }
if (!ret) if (!ret)
@ -335,7 +340,7 @@ parse_error (const GError *error,
} }
GtkWidget * GtkWidget *
xed_unrecoverable_reverting_error_message_area_new (const gchar *uri, xed_unrecoverable_reverting_error_message_area_new (GFile *location,
const GError *error) const GError *error)
{ {
gchar *error_message = NULL; gchar *error_message = NULL;
@ -345,11 +350,11 @@ xed_unrecoverable_reverting_error_message_area_new (const gchar *uri,
gchar *temp_uri_for_display; gchar *temp_uri_for_display;
GtkWidget *message_area; GtkWidget *message_area;
g_return_val_if_fail (uri != NULL, NULL); g_return_val_if_fail (G_IS_FILE (location), NULL);
g_return_val_if_fail (error != NULL, NULL); g_return_val_if_fail (error != NULL, NULL);
g_return_val_if_fail ((error->domain == XED_DOCUMENT_ERROR) || (error->domain == G_IO_ERROR), NULL); g_return_val_if_fail ((error->domain == XED_DOCUMENT_ERROR) || (error->domain == G_IO_ERROR), NULL);
full_formatted_uri = xed_utils_uri_for_display (uri); full_formatted_uri = xed_utils_uri_for_display (location);
/* Truncate the URI so it doesn't get insanely wide. Note that even /* Truncate the URI so it doesn't get insanely wide. Note that even
* though the dialog uses wrapped text, if the URI doesn't contain * though the dialog uses wrapped text, if the URI doesn't contain
@ -368,7 +373,7 @@ xed_unrecoverable_reverting_error_message_area_new (const gchar *uri,
} }
else else
{ {
parse_error (error, &error_message, &message_details, uri, uri_for_display); parse_error (error, &error_message, &message_details, location, uri_for_display);
} }
if (error_message == NULL) if (error_message == NULL)
@ -491,7 +496,7 @@ create_conversion_error_message_area (const gchar *primary_text,
} }
GtkWidget * GtkWidget *
xed_io_loading_error_message_area_new (const gchar *uri, xed_io_loading_error_message_area_new (GFile *location,
const XedEncoding *encoding, const XedEncoding *encoding,
const GError *error) const GError *error)
{ {
@ -505,13 +510,13 @@ xed_io_loading_error_message_area_new (const gchar *uri,
gboolean edit_anyway = FALSE; gboolean edit_anyway = FALSE;
gboolean convert_error = FALSE; gboolean convert_error = FALSE;
g_return_val_if_fail (uri != NULL, NULL); g_return_val_if_fail (G_IS_FILE (location), NULL);
g_return_val_if_fail (error != NULL, NULL); g_return_val_if_fail (error != NULL, NULL);
g_return_val_if_fail ((error->domain == G_CONVERT_ERROR) || g_return_val_if_fail ((error->domain == G_CONVERT_ERROR) ||
(error->domain == XED_DOCUMENT_ERROR) || (error->domain == XED_DOCUMENT_ERROR) ||
(error->domain == G_IO_ERROR), NULL); (error->domain == G_IO_ERROR), NULL);
full_formatted_uri = xed_utils_uri_for_display (uri); full_formatted_uri = xed_utils_uri_for_display (location);
/* Truncate the URI so it doesn't get insanely wide. Note that even /* Truncate the URI so it doesn't get insanely wide. Note that even
* though the dialog uses wrapped text, if the URI doesn't contain * though the dialog uses wrapped text, if the URI doesn't contain
@ -572,7 +577,7 @@ xed_io_loading_error_message_area_new (const gchar *uri,
} }
else else
{ {
parse_error (error, &error_message, &message_details, uri, uri_for_display); parse_error (error, &error_message, &message_details, location, uri_for_display);
} }
if (error_message == NULL) if (error_message == NULL)
@ -600,7 +605,7 @@ xed_io_loading_error_message_area_new (const gchar *uri,
} }
GtkWidget * GtkWidget *
xed_conversion_error_while_saving_message_area_new (const gchar *uri, xed_conversion_error_while_saving_message_area_new (GFile *location,
const XedEncoding *encoding, const XedEncoding *encoding,
const GError *error) const GError *error)
{ {
@ -612,13 +617,13 @@ xed_conversion_error_while_saving_message_area_new (const gchar *uri,
gchar *temp_uri_for_display; gchar *temp_uri_for_display;
GtkWidget *message_area; GtkWidget *message_area;
g_return_val_if_fail (uri != NULL, NULL); g_return_val_if_fail (G_IS_FILE (location), NULL);
g_return_val_if_fail (error != NULL, NULL); g_return_val_if_fail (error != NULL, NULL);
g_return_val_if_fail (error->domain == G_CONVERT_ERROR || g_return_val_if_fail (error->domain == G_CONVERT_ERROR ||
error->domain == G_IO_ERROR, NULL); error->domain == G_IO_ERROR, NULL);
g_return_val_if_fail (encoding != NULL, NULL); g_return_val_if_fail (encoding != NULL, NULL);
full_formatted_uri = xed_utils_uri_for_display (uri); full_formatted_uri = xed_utils_uri_for_display (location);
/* Truncate the URI so it doesn't get insanely wide. Note that even /* Truncate the URI so it doesn't get insanely wide. Note that even
* though the dialog uses wrapped text, if the URI doesn't contain * though the dialog uses wrapped text, if the URI doesn't contain
@ -663,7 +668,7 @@ xed_conversion_error_message_area_get_encoding (GtkWidget *message_area)
} }
GtkWidget * GtkWidget *
xed_file_already_open_warning_message_area_new (const gchar *uri) xed_file_already_open_warning_message_area_new (GFile *location)
{ {
GtkWidget *message_area; GtkWidget *message_area;
GtkWidget *hbox_content; GtkWidget *hbox_content;
@ -679,7 +684,9 @@ xed_file_already_open_warning_message_area_new (const gchar *uri)
gchar *uri_for_display; gchar *uri_for_display;
gchar *temp_uri_for_display; gchar *temp_uri_for_display;
full_formatted_uri = xed_utils_uri_for_display (uri); g_return_val_if_fail (G_IS_FILE (location), NULL);
full_formatted_uri = xed_utils_uri_for_display (location);
/* Truncate the URI so it doesn't get insanely wide. Note that even /* Truncate the URI so it doesn't get insanely wide. Note that even
* though the dialog uses wrapped text, if the URI doesn't contain * though the dialog uses wrapped text, if the URI doesn't contain
@ -747,7 +754,7 @@ xed_file_already_open_warning_message_area_new (const gchar *uri)
} }
GtkWidget * GtkWidget *
xed_externally_modified_saving_error_message_area_new (const gchar *uri, xed_externally_modified_saving_error_message_area_new (GFile *location,
const GError *error) const GError *error)
{ {
GtkWidget *message_area; GtkWidget *message_area;
@ -764,12 +771,12 @@ xed_externally_modified_saving_error_message_area_new (const gchar *uri,
gchar *uri_for_display; gchar *uri_for_display;
gchar *temp_uri_for_display; gchar *temp_uri_for_display;
g_return_val_if_fail (uri != NULL, NULL); g_return_val_if_fail (G_IS_FILE (location), NULL);
g_return_val_if_fail (error != NULL, NULL); g_return_val_if_fail (error != NULL, NULL);
g_return_val_if_fail (error->domain == XED_DOCUMENT_ERROR, NULL); g_return_val_if_fail (error->domain == XED_DOCUMENT_ERROR, NULL);
g_return_val_if_fail (error->code == XED_DOCUMENT_ERROR_EXTERNALLY_MODIFIED, NULL); g_return_val_if_fail (error->code == XED_DOCUMENT_ERROR_EXTERNALLY_MODIFIED, NULL);
full_formatted_uri = xed_utils_uri_for_display (uri); full_formatted_uri = xed_utils_uri_for_display (location);
/* Truncate the URI so it doesn't get insanely wide. Note that even /* Truncate the URI so it doesn't get insanely wide. Note that even
* though the dialog uses wrapped text, if the URI doesn't contain * though the dialog uses wrapped text, if the URI doesn't contain
@ -833,7 +840,7 @@ xed_externally_modified_saving_error_message_area_new (const gchar *uri,
} }
GtkWidget * GtkWidget *
xed_no_backup_saving_error_message_area_new (const gchar *uri, xed_no_backup_saving_error_message_area_new (GFile *location,
const GError *error) const GError *error)
{ {
GtkWidget *message_area; GtkWidget *message_area;
@ -850,14 +857,14 @@ xed_no_backup_saving_error_message_area_new (const gchar *uri,
gchar *uri_for_display; gchar *uri_for_display;
gchar *temp_uri_for_display; gchar *temp_uri_for_display;
g_return_val_if_fail (uri != NULL, NULL); g_return_val_if_fail (G_IS_FILE (location), NULL);
g_return_val_if_fail (error != NULL, NULL); g_return_val_if_fail (error != NULL, NULL);
g_return_val_if_fail (((error->domain == XED_DOCUMENT_ERROR && g_return_val_if_fail (((error->domain == XED_DOCUMENT_ERROR &&
error->code == XED_DOCUMENT_ERROR_CANT_CREATE_BACKUP) || error->code == XED_DOCUMENT_ERROR_CANT_CREATE_BACKUP) ||
(error->domain == G_IO_ERROR && (error->domain == G_IO_ERROR &&
error->code == G_IO_ERROR_CANT_CREATE_BACKUP)), NULL); error->code == G_IO_ERROR_CANT_CREATE_BACKUP)), NULL);
full_formatted_uri = xed_utils_uri_for_display (uri); full_formatted_uri = xed_utils_uri_for_display (location);
/* Truncate the URI so it doesn't get insanely wide. Note that even /* Truncate the URI so it doesn't get insanely wide. Note that even
* though the dialog uses wrapped text, if the URI doesn't contain * though the dialog uses wrapped text, if the URI doesn't contain
@ -930,7 +937,7 @@ xed_no_backup_saving_error_message_area_new (const gchar *uri,
} }
GtkWidget * GtkWidget *
xed_unrecoverable_saving_error_message_area_new (const gchar *uri, xed_unrecoverable_saving_error_message_area_new (GFile *location,
const GError *error) const GError *error)
{ {
gchar *error_message = NULL; gchar *error_message = NULL;
@ -942,11 +949,11 @@ xed_unrecoverable_saving_error_message_area_new (const gchar *uri,
gchar *temp_uri_for_display; gchar *temp_uri_for_display;
GtkWidget *message_area; GtkWidget *message_area;
g_return_val_if_fail (uri != NULL, NULL); g_return_val_if_fail (G_IS_FILE (location), NULL);
g_return_val_if_fail (error != NULL, NULL); g_return_val_if_fail (error != NULL, NULL);
g_return_val_if_fail ((error->domain == XED_DOCUMENT_ERROR) || (error->domain == G_IO_ERROR), NULL); g_return_val_if_fail ((error->domain == XED_DOCUMENT_ERROR) || (error->domain == G_IO_ERROR), NULL);
full_formatted_uri = xed_utils_uri_for_display (uri); full_formatted_uri = xed_utils_uri_for_display (location);
/* Truncate the URI so it doesn't get insanely wide. Note that even /* Truncate the URI so it doesn't get insanely wide. Note that even
* though the dialog uses wrapped text, if the URI doesn't contain * though the dialog uses wrapped text, if the URI doesn't contain
@ -960,7 +967,7 @@ xed_unrecoverable_saving_error_message_area_new (const gchar *uri,
if (is_gio_error (error, G_IO_ERROR_NOT_SUPPORTED)) if (is_gio_error (error, G_IO_ERROR_NOT_SUPPORTED))
{ {
scheme_string = g_uri_parse_scheme (uri); scheme_string = g_file_get_uri_scheme (location);
if ((scheme_string != NULL) && g_utf8_validate (scheme_string, -1, NULL)) if ((scheme_string != NULL) && g_utf8_validate (scheme_string, -1, NULL))
{ {
@ -1025,7 +1032,7 @@ xed_unrecoverable_saving_error_message_area_new (const gchar *uri,
} }
else else
{ {
parse_error (error, &error_message, &message_details, uri, uri_for_display); parse_error (error, &error_message, &message_details, location, uri_for_display);
} }
if (error_message == NULL) if (error_message == NULL)
@ -1043,7 +1050,7 @@ xed_unrecoverable_saving_error_message_area_new (const gchar *uri,
} }
GtkWidget * GtkWidget *
xed_externally_modified_message_area_new (const gchar *uri, xed_externally_modified_message_area_new (GFile *location,
gboolean document_modified) gboolean document_modified)
{ {
gchar *full_formatted_uri; gchar *full_formatted_uri;
@ -1053,9 +1060,9 @@ xed_externally_modified_message_area_new (const gchar *uri,
const gchar *secondary_text; const gchar *secondary_text;
GtkWidget *message_area; GtkWidget *message_area;
g_return_val_if_fail (uri != NULL, NULL); g_return_val_if_fail (G_IS_FILE (location), NULL);
full_formatted_uri = xed_utils_uri_for_display (uri); full_formatted_uri = xed_utils_uri_for_display (location);
/* Truncate the URI so it doesn't get insanely wide. Note that even /* Truncate the URI so it doesn't get insanely wide. Note that even
* though the dialog uses wrapped text, if the URI doesn't contain * though the dialog uses wrapped text, if the URI doesn't contain

View File

@ -35,32 +35,32 @@
G_BEGIN_DECLS G_BEGIN_DECLS
GtkWidget *xed_io_loading_error_message_area_new (const gchar *uri, GtkWidget *xed_io_loading_error_message_area_new (GFile *location,
const XedEncoding *encoding, const XedEncoding *encoding,
const GError *error); const GError *error);
GtkWidget *xed_unrecoverable_reverting_error_message_area_new (const gchar *uri, GtkWidget *xed_unrecoverable_reverting_error_message_area_new (GFile *location,
const GError *error); const GError *error);
GtkWidget *xed_conversion_error_while_saving_message_area_new (const gchar *uri, GtkWidget *xed_conversion_error_while_saving_message_area_new (GFile *location,
const XedEncoding *encoding, const XedEncoding *encoding,
const GError *error); const GError *error);
const XedEncoding const XedEncoding
*xed_conversion_error_message_area_get_encoding (GtkWidget *message_area); *xed_conversion_error_message_area_get_encoding (GtkWidget *message_area);
GtkWidget *xed_file_already_open_warning_message_area_new (const gchar *uri); GtkWidget *xed_file_already_open_warning_message_area_new (GFile *location);
GtkWidget *xed_externally_modified_saving_error_message_area_new (const gchar *uri, GtkWidget *xed_externally_modified_saving_error_message_area_new (GFile *location,
const GError *error); const GError *error);
GtkWidget *xed_no_backup_saving_error_message_area_new (const gchar *uri, GtkWidget *xed_no_backup_saving_error_message_area_new (GFile *location,
const GError *error); const GError *error);
GtkWidget *xed_unrecoverable_saving_error_message_area_new (const gchar *uri, GtkWidget *xed_unrecoverable_saving_error_message_area_new (GFile *location,
const GError *error); const GError *error);
GtkWidget *xed_externally_modified_message_area_new (const gchar *uri, GtkWidget *xed_externally_modified_message_area_new (GFile *location,
gboolean document_modified); gboolean document_modified);
G_END_DECLS G_END_DECLS

View File

@ -5,8 +5,8 @@ VOID:BOOLEAN,POINTER
VOID:BOXED,BOXED VOID:BOXED,BOXED
VOID:OBJECT VOID:OBJECT
VOID:POINTER VOID:POINTER
VOID:STRING,BOXED,FLAGS VOID:OBJECT,BOXED,FLAGS
VOID:STRING,BOXED,INT,BOOLEAN VOID:OBJECT,BOXED,INT,BOOLEAN
VOID:UINT,POINTER VOID:UINT,POINTER
VOID:UINT64,UINT64 VOID:UINT64,UINT64
VOID:VOID VOID:VOID

View File

@ -301,15 +301,18 @@ load_values (void)
} }
gchar * gchar *
xed_metadata_manager_get (const gchar *uri, xed_metadata_manager_get (GFile *location,
const gchar *key) const gchar *key)
{ {
Item *item; Item *item;
gchar *value; gchar *value;
gchar *uri;
g_return_val_if_fail (uri != NULL, NULL); g_return_val_if_fail (G_IS_FILE (location), NULL);
g_return_val_if_fail (key != NULL, NULL); g_return_val_if_fail (key != NULL, NULL);
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 );
xed_metadata_manager_init (); xed_metadata_manager_init ();
@ -327,6 +330,8 @@ xed_metadata_manager_get (const gchar *uri,
item = (Item *)g_hash_table_lookup (xed_metadata_manager->items, item = (Item *)g_hash_table_lookup (xed_metadata_manager->items,
uri); uri);
g_free (uri);
if (item == NULL) if (item == NULL)
return NULL; return NULL;
@ -344,15 +349,18 @@ xed_metadata_manager_get (const gchar *uri,
} }
void void
xed_metadata_manager_set (const gchar *uri, xed_metadata_manager_set (GFile *location,
const gchar *key, const gchar *key,
const gchar *value) const gchar *value)
{ {
Item *item; Item *item;
gchar *uri;
g_return_if_fail (uri != NULL); g_return_if_fail (G_IS_FILE (location));
g_return_if_fail (key != NULL); g_return_if_fail (key != NULL);
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);
xed_metadata_manager_init (); xed_metadata_manager_init ();
@ -394,6 +402,8 @@ xed_metadata_manager_set (const gchar *uri,
item->atime = time (NULL); item->atime = time (NULL);
g_free (uri);
xed_metadata_manager_arm_timeout (); xed_metadata_manager_arm_timeout ();
} }

View File

@ -39,9 +39,9 @@ G_BEGIN_DECLS
void xed_metadata_manager_shutdown (void); void xed_metadata_manager_shutdown (void);
gchar *xed_metadata_manager_get (const gchar *uri, gchar *xed_metadata_manager_get (GFile *location,
const gchar *key); const gchar *key);
void xed_metadata_manager_set (const gchar *uri, void xed_metadata_manager_set (GFile *location,
const gchar *key, const gchar *key,
const gchar *value); const gchar *value);

View File

@ -75,7 +75,7 @@ save_window_session (GKeyFile *state_file,
GList *docs, *l; GList *docs, *l;
GPtrArray *doc_array; GPtrArray *doc_array;
XedDocument *active_document; XedDocument *active_document;
gchar *uri; gchar *uri = NULL;
xed_debug (DEBUG_SESSION); xed_debug (DEBUG_SESSION);
@ -96,9 +96,17 @@ save_window_session (GKeyFile *state_file,
active_document = xed_window_get_active_document (window); active_document = xed_window_get_active_document (window);
if (active_document) if (active_document)
{ {
uri = xed_document_get_uri (active_document); GFile *location;
g_key_file_set_string (state_file, group_name,
"active-document", uri); location = xed_document_get_location (active_document);
if (location)
{
uri = g_file_get_uri (location);
g_object_unref (location);
}
g_key_file_set_string (state_file, group_name, "active-document", uri);
g_free (uri);
} }
docs = xed_window_get_documents (window); docs = xed_window_get_documents (window);
@ -106,24 +114,30 @@ save_window_session (GKeyFile *state_file,
doc_array = g_ptr_array_new (); doc_array = g_ptr_array_new ();
for (l = docs; l != NULL; l = g_list_next (l)) for (l = docs; l != NULL; l = g_list_next (l))
{ {
uri = xed_document_get_uri (XED_DOCUMENT (l->data)); GFile *location;
location = xed_document_get_location (XED_DOCUMENT (l->data));
if (location)
{
uri = g_file_get_uri (location);
g_object_unref (location);
}
if (uri != NULL) if (uri != NULL)
{
g_ptr_array_add (doc_array, uri); g_ptr_array_add (doc_array, uri);
}
} }
g_list_free (docs); g_list_free (docs);
if (doc_array->len) if (doc_array->len)
{ {
guint i;
g_key_file_set_string_list (state_file, group_name, g_key_file_set_string_list (state_file, group_name,
"documents", "documents",
(const char **)doc_array->pdata, (const char **)doc_array->pdata,
doc_array->len); doc_array->len);
for (i = 0; i < doc_array->len; i++) g_ptr_array_foreach (doc_array, (GFunc) g_free, NULL);
g_free (doc_array->pdata[i]);
} }
g_ptr_array_free (doc_array, TRUE); g_ptr_array_free (doc_array, TRUE);
} }
@ -537,25 +551,29 @@ parse_window (GKeyFile *state_file, const char *group_name)
"documents", NULL, NULL); "documents", NULL, NULL);
if (documents) if (documents)
{ {
int i; gint i;
gboolean jump_to = FALSE; gboolean jump_to = FALSE;
for (i = 0; documents[i]; i++) for (i = 0; documents[i]; i++)
{ {
GFile *location;
if (active_document != NULL) if (active_document != NULL)
jump_to = strcmp (active_document, {
documents[i]) == 0; jump_to = strcmp (active_document, documents[i]) == 0;
}
xed_debug_message (DEBUG_SESSION, xed_debug_message (DEBUG_SESSION,
"URI: %s (%s)", "URI: %s (%s)",
documents[i], documents[i],
jump_to ? "active" : "not active"); jump_to ? "active" : "not active");
xed_window_create_tab_from_uri (window,
documents[i], location = g_file_new_for_uri (documents[i]);
NULL, xed_window_create_tab_from_location (window, location, NULL, 0, FALSE, jump_to);
0, if (location)
FALSE, {
jump_to); g_object_unref (location);
}
} }
g_strfreev (documents); g_strfreev (documents);
} }

View File

@ -62,7 +62,7 @@ struct _XedTabPrivate
XedPrintJob *print_job; XedPrintJob *print_job;
/* tmp data for saving */ /* tmp data for saving */
gchar *tmp_save_uri; GFile *tmp_save_location;
/* tmp data for loading */ /* tmp data for loading */
gint tmp_line_pos; gint tmp_line_pos;
@ -212,6 +212,20 @@ xed_tab_set_property (GObject *object,
} }
} }
static void
xed_tab_dispose (GObject *object)
{
XedTab *tab = XED_TAB (object);
if (tab->priv->tmp_save_location != NULL)
{
g_object_unref (tab->priv->tmp_save_location);
tab->priv->tmp_save_location = NULL;
}
G_OBJECT_CLASS (xed_tab_parent_class)->dispose (object);
}
static void static void
xed_tab_finalize (GObject *object) xed_tab_finalize (GObject *object)
{ {
@ -222,8 +236,6 @@ xed_tab_finalize (GObject *object)
g_timer_destroy (tab->priv->timer); g_timer_destroy (tab->priv->timer);
} }
g_free (tab->priv->tmp_save_uri);
if (tab->priv->auto_save_timeout > 0) if (tab->priv->auto_save_timeout > 0)
{ {
remove_auto_save_timeout (tab); remove_auto_save_timeout (tab);
@ -237,6 +249,7 @@ xed_tab_class_init (XedTabClass *klass)
{ {
GObjectClass *object_class = G_OBJECT_CLASS (klass); GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->dispose = xed_tab_dispose;
object_class->finalize = xed_tab_finalize; object_class->finalize = xed_tab_finalize;
object_class->get_property = xed_tab_get_property; object_class->get_property = xed_tab_get_property;
object_class->set_property = xed_tab_set_property; object_class->set_property = xed_tab_set_property;
@ -407,13 +420,13 @@ xed_tab_set_state (XedTab *tab,
} }
static void static void
document_uri_notify_handler (XedDocument *document, document_location_notify_handler (XedDocument *document,
GParamSpec *pspec, GParamSpec *pspec,
XedTab *tab) XedTab *tab)
{ {
xed_debug (DEBUG_TAB); xed_debug (DEBUG_TAB);
/* Notify the change in the URI */ /* Notify the change in the location */
g_object_notify (G_OBJECT (tab), "name"); g_object_notify (G_OBJECT (tab), "name");
} }
@ -478,7 +491,7 @@ io_loading_error_message_area_response (GtkWidget *message_area,
{ {
XedDocument *doc; XedDocument *doc;
XedView *view; XedView *view;
gchar *uri; GFile *location;
const XedEncoding *encoding; const XedEncoding *encoding;
doc = xed_tab_get_document (tab); doc = xed_tab_get_document (tab);
@ -487,8 +500,8 @@ io_loading_error_message_area_response (GtkWidget *message_area,
view = xed_tab_get_view (tab); view = xed_tab_get_view (tab);
g_return_if_fail (XED_IS_VIEW (view)); g_return_if_fail (XED_IS_VIEW (view));
uri = xed_document_get_uri (doc); location = xed_document_get_location (doc);
g_return_if_fail (uri != NULL); g_return_if_fail (location != NULL);
switch (response_id) switch (response_id)
{ {
@ -505,7 +518,7 @@ io_loading_error_message_area_response (GtkWidget *message_area,
g_return_if_fail (tab->priv->auto_save_timeout <= 0); g_return_if_fail (tab->priv->auto_save_timeout <= 0);
xed_document_load (doc, uri, tab->priv->tmp_encoding, tab->priv->tmp_line_pos, FALSE); xed_document_load (doc, location, tab->priv->tmp_encoding, tab->priv->tmp_line_pos, FALSE);
break; break;
case GTK_RESPONSE_YES: case GTK_RESPONSE_YES:
/* This means that we want to edit the document anyway */ /* This means that we want to edit the document anyway */
@ -517,13 +530,13 @@ io_loading_error_message_area_response (GtkWidget *message_area,
set_message_area (tab, NULL); set_message_area (tab, NULL);
break; break;
default: default:
_xed_recent_remove (XED_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (tab))), uri); _xed_recent_remove (XED_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (tab))), location);
remove_tab (tab); remove_tab (tab);
break; break;
} }
g_free (uri); g_object_unref (location);
} }
static void static void
@ -618,15 +631,15 @@ show_loading_message_area (XedTab *tab)
} }
else else
{ {
GFile *file; GFile *location;
file = xed_document_get_location (doc); location = xed_document_get_location (doc);
if (file != NULL) if (location != NULL)
{ {
gchar *str; gchar *str;
str = xed_utils_location_get_dirname_for_display (file); str = xed_utils_location_get_dirname_for_display (location);
g_object_unref (file); g_object_unref (location);
/* use the remaining space for the dir, but use a min of 20 chars /* use the remaining space for the dir, but use a min of 20 chars
* so that we do not end up with a dirname like "(a...b)". * so that we do not end up with a dirname like "(a...b)".
@ -704,7 +717,7 @@ show_saving_message_area (XedTab *tab)
gchar *msg = NULL; gchar *msg = NULL;
gint len; gint len;
g_return_if_fail (tab->priv->tmp_save_uri != NULL); g_return_if_fail (tab->priv->tmp_save_location != NULL);
if (tab->priv->message_area != NULL) if (tab->priv->message_area != NULL)
{ {
@ -734,7 +747,7 @@ show_saving_message_area (XedTab *tab)
from = short_name; from = short_name;
to = xed_utils_uri_for_display (tab->priv->tmp_save_uri); to = xed_utils_uri_for_display (tab->priv->tmp_save_location);
str = xed_utils_str_middle_truncate (to, MAX (20, MAX_MSG_LENGTH - len)); str = xed_utils_str_middle_truncate (to, MAX (20, MAX_MSG_LENGTH - len));
g_free (to); g_free (to);
@ -848,7 +861,6 @@ document_loaded (XedDocument *document,
{ {
GtkWidget *emsg; GtkWidget *emsg;
GFile *location; GFile *location;
gchar *uri;
const XedEncoding *encoding; const XedEncoding *encoding;
g_return_if_fail ((tab->priv->state == XED_TAB_STATE_LOADING) || (tab->priv->state == XED_TAB_STATE_REVERTING)); g_return_if_fail ((tab->priv->state == XED_TAB_STATE_LOADING) || (tab->priv->state == XED_TAB_STATE_REVERTING));
@ -864,7 +876,6 @@ document_loaded (XedDocument *document,
set_message_area (tab, NULL); set_message_area (tab, NULL);
location = xed_document_get_location (document); location = xed_document_get_location (document);
uri = xed_document_get_uri (document);
/* if the error is CONVERSION FALLBACK don't treat it as a normal error */ /* if the error is CONVERSION FALLBACK don't treat it as a normal error */
if (error != NULL && (error->domain != XED_DOCUMENT_ERROR || error->code != XED_DOCUMENT_ERROR_CONVERSION_FALLBACK)) if (error != NULL && (error->domain != XED_DOCUMENT_ERROR || error->code != XED_DOCUMENT_ERROR_CONVERSION_FALLBACK))
@ -892,11 +903,11 @@ document_loaded (XedDocument *document,
} }
else else
{ {
_xed_recent_remove (XED_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (tab))), uri); _xed_recent_remove (XED_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (tab))), location);
if (tab->priv->state == XED_TAB_STATE_LOADING_ERROR) if (tab->priv->state == XED_TAB_STATE_LOADING_ERROR)
{ {
emsg = xed_io_loading_error_message_area_new (uri, tab->priv->tmp_encoding, error); emsg = xed_io_loading_error_message_area_new (location, tab->priv->tmp_encoding, error);
g_signal_connect (emsg, "response", g_signal_connect (emsg, "response",
G_CALLBACK (io_loading_error_message_area_response), tab); G_CALLBACK (io_loading_error_message_area_response), tab);
} }
@ -904,7 +915,7 @@ document_loaded (XedDocument *document,
{ {
g_return_if_fail (tab->priv->state == XED_TAB_STATE_REVERTING_ERROR); g_return_if_fail (tab->priv->state == XED_TAB_STATE_REVERTING_ERROR);
emsg = xed_unrecoverable_reverting_error_message_area_new (uri, error); emsg = xed_unrecoverable_reverting_error_message_area_new (location, error);
g_signal_connect (emsg, "response", g_signal_connect (emsg, "response",
G_CALLBACK (unrecoverable_reverting_error_message_area_response), tab); G_CALLBACK (unrecoverable_reverting_error_message_area_response), tab);
@ -918,7 +929,6 @@ document_loaded (XedDocument *document,
gtk_widget_show (emsg); gtk_widget_show (emsg);
g_object_unref (location); g_object_unref (location);
g_free (uri);
return; return;
} }
@ -928,10 +938,10 @@ document_loaded (XedDocument *document,
GList *all_documents; GList *all_documents;
GList *l; GList *l;
g_return_if_fail (uri != NULL); g_return_if_fail (location != NULL);
mime = xed_document_get_mime_type (document); mime = xed_document_get_mime_type (document);
_xed_recent_add (XED_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (tab))), uri, mime); _xed_recent_add (XED_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (tab))), location, mime);
g_free (mime); g_free (mime);
if (error && error->domain == XED_DOCUMENT_ERROR && error->code == XED_DOCUMENT_ERROR_CONVERSION_FALLBACK) if (error && error->domain == XED_DOCUMENT_ERROR && error->code == XED_DOCUMENT_ERROR_CONVERSION_FALLBACK)
@ -940,7 +950,7 @@ document_loaded (XedDocument *document,
_xed_document_set_readonly (document, TRUE); _xed_document_set_readonly (document, TRUE);
emsg = xed_io_loading_error_message_area_new (uri, tab->priv->tmp_encoding, error); emsg = xed_io_loading_error_message_area_new (location, tab->priv->tmp_encoding, error);
set_message_area (tab, emsg); set_message_area (tab, emsg);
@ -976,7 +986,7 @@ document_loaded (XedDocument *document,
tab->priv->not_editable = TRUE; tab->priv->not_editable = TRUE;
w = xed_file_already_open_warning_message_area_new (uri); w = xed_file_already_open_warning_message_area_new (location);
set_message_area (tab, w); set_message_area (tab, w);
@ -1009,7 +1019,6 @@ document_loaded (XedDocument *document,
end: end:
g_object_unref (location); g_object_unref (location);
g_free (uri);
tab->priv->tmp_line_pos = 0; tab->priv->tmp_line_pos = 0;
tab->priv->tmp_encoding = NULL; tab->priv->tmp_encoding = NULL;
@ -1054,8 +1063,11 @@ static void
end_saving (XedTab *tab) end_saving (XedTab *tab)
{ {
/* Reset tmp data for saving */ /* Reset tmp data for saving */
g_free (tab->priv->tmp_save_uri); if (tab->priv->tmp_save_location)
tab->priv->tmp_save_uri = NULL; {
g_object_unref (tab->priv->tmp_save_location);
tab->priv->tmp_save_location = NULL;
}
tab->priv->tmp_encoding = NULL; tab->priv->tmp_encoding = NULL;
install_auto_save_timeout_if_needed (tab); install_auto_save_timeout_if_needed (tab);
@ -1100,7 +1112,7 @@ no_backup_error_message_area_response (GtkWidget *message_area,
set_message_area (tab, NULL); set_message_area (tab, NULL);
g_return_if_fail (tab->priv->tmp_save_uri != NULL); g_return_if_fail (tab->priv->tmp_save_location != NULL);
g_return_if_fail (tab->priv->tmp_encoding != NULL); g_return_if_fail (tab->priv->tmp_encoding != NULL);
xed_tab_set_state (tab, XED_TAB_STATE_SAVING); xed_tab_set_state (tab, XED_TAB_STATE_SAVING);
@ -1133,7 +1145,7 @@ externally_modified_error_message_area_response (GtkWidget *message_area,
set_message_area (tab, NULL); set_message_area (tab, NULL);
g_return_if_fail (tab->priv->tmp_save_uri != NULL); g_return_if_fail (tab->priv->tmp_save_location != NULL);
g_return_if_fail (tab->priv->tmp_encoding != NULL); g_return_if_fail (tab->priv->tmp_encoding != NULL);
xed_tab_set_state (tab, XED_TAB_STATE_SAVING); xed_tab_set_state (tab, XED_TAB_STATE_SAVING);
@ -1164,6 +1176,7 @@ recoverable_saving_error_message_area_response (GtkWidget *message_area,
if (response_id == GTK_RESPONSE_OK) if (response_id == GTK_RESPONSE_OK)
{ {
const XedEncoding *encoding; const XedEncoding *encoding;
gchar *tmp_uri;
encoding = xed_conversion_error_message_area_get_encoding (GTK_WIDGET (message_area)); encoding = xed_conversion_error_message_area_get_encoding (GTK_WIDGET (message_area));
@ -1171,17 +1184,19 @@ recoverable_saving_error_message_area_response (GtkWidget *message_area,
set_message_area (tab, NULL); set_message_area (tab, NULL);
g_return_if_fail (tab->priv->tmp_save_uri != NULL); g_return_if_fail (tab->priv->tmp_save_location != NULL);
xed_tab_set_state (tab, XED_TAB_STATE_SAVING); xed_tab_set_state (tab, XED_TAB_STATE_SAVING);
tab->priv->tmp_encoding = encoding; tab->priv->tmp_encoding = encoding;
xed_debug_message (DEBUG_TAB, "Force saving with URI '%s'", tab->priv->tmp_save_uri); tmp_uri = g_file_get_uri (tab->priv->tmp_save_location);
xed_debug_message (DEBUG_TAB, "Force saving with URI '%s'", tmp_uri);
g_free (tmp_uri);
g_return_if_fail (tab->priv->auto_save_timeout <= 0); g_return_if_fail (tab->priv->auto_save_timeout <= 0);
xed_document_save_as (doc, tab->priv->tmp_save_uri, tab->priv->tmp_encoding, tab->priv->save_flags); xed_document_save_as (doc, tab->priv->tmp_save_location, tab->priv->tmp_encoding, tab->priv->save_flags);
} }
else else
{ {
@ -1198,7 +1213,7 @@ document_saved (XedDocument *document,
g_return_if_fail (tab->priv->state == XED_TAB_STATE_SAVING); g_return_if_fail (tab->priv->state == XED_TAB_STATE_SAVING);
g_return_if_fail (tab->priv->tmp_save_uri != NULL); g_return_if_fail (tab->priv->tmp_save_location != NULL);
g_return_if_fail (tab->priv->tmp_encoding != NULL); g_return_if_fail (tab->priv->tmp_encoding != NULL);
g_return_if_fail (tab->priv->auto_save_timeout <= 0); g_return_if_fail (tab->priv->auto_save_timeout <= 0);
@ -1215,7 +1230,7 @@ document_saved (XedDocument *document,
if (error->domain == XED_DOCUMENT_ERROR && error->code == XED_DOCUMENT_ERROR_EXTERNALLY_MODIFIED) if (error->domain == XED_DOCUMENT_ERROR && error->code == XED_DOCUMENT_ERROR_EXTERNALLY_MODIFIED)
{ {
/* This error is recoverable */ /* This error is recoverable */
emsg = xed_externally_modified_saving_error_message_area_new (tab->priv->tmp_save_uri, error); emsg = xed_externally_modified_saving_error_message_area_new (tab->priv->tmp_save_location, error);
g_return_if_fail (emsg != NULL); g_return_if_fail (emsg != NULL);
set_message_area (tab, emsg); set_message_area (tab, emsg);
@ -1229,7 +1244,7 @@ document_saved (XedDocument *document,
error->code == G_IO_ERROR_CANT_CREATE_BACKUP)) error->code == G_IO_ERROR_CANT_CREATE_BACKUP))
{ {
/* This error is recoverable */ /* This error is recoverable */
emsg = xed_no_backup_saving_error_message_area_new (tab->priv->tmp_save_uri, error); emsg = xed_no_backup_saving_error_message_area_new (tab->priv->tmp_save_location, error);
g_return_if_fail (emsg != NULL); g_return_if_fail (emsg != NULL);
set_message_area (tab, emsg); set_message_area (tab, emsg);
@ -1243,9 +1258,9 @@ document_saved (XedDocument *document,
error->code != G_IO_ERROR_PARTIAL_INPUT)) error->code != G_IO_ERROR_PARTIAL_INPUT))
{ {
/* These errors are _NOT_ recoverable */ /* These errors are _NOT_ recoverable */
_xed_recent_remove (XED_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (tab))), tab->priv->tmp_save_uri); _xed_recent_remove (XED_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (tab))), tab->priv->tmp_save_location);
emsg = xed_unrecoverable_saving_error_message_area_new (tab->priv->tmp_save_uri, error); emsg = xed_unrecoverable_saving_error_message_area_new (tab->priv->tmp_save_location, error);
g_return_if_fail (emsg != NULL); g_return_if_fail (emsg != NULL);
set_message_area (tab, emsg); set_message_area (tab, emsg);
@ -1258,7 +1273,7 @@ document_saved (XedDocument *document,
/* This error is recoverable */ /* This error is recoverable */
g_return_if_fail (error->domain == G_CONVERT_ERROR || error->domain == G_IO_ERROR); g_return_if_fail (error->domain == G_CONVERT_ERROR || error->domain == G_IO_ERROR);
emsg = xed_conversion_error_while_saving_message_area_new (tab->priv->tmp_save_uri, emsg = xed_conversion_error_while_saving_message_area_new (tab->priv->tmp_save_location,
tab->priv->tmp_encoding, tab->priv->tmp_encoding,
error); error);
@ -1276,7 +1291,7 @@ document_saved (XedDocument *document,
{ {
gchar *mime = xed_document_get_mime_type (document); gchar *mime = xed_document_get_mime_type (document);
_xed_recent_add (XED_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (tab))), tab->priv->tmp_save_uri, mime); _xed_recent_add (XED_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (tab))), tab->priv->tmp_save_location, mime);
g_free (mime); g_free (mime);
if (tab->priv->print_preview != NULL) if (tab->priv->print_preview != NULL)
@ -1324,20 +1339,19 @@ display_externally_modified_notification (XedTab *tab)
{ {
GtkWidget *message_area; GtkWidget *message_area;
XedDocument *doc; XedDocument *doc;
gchar *uri; GFile *location;
gboolean document_modified; gboolean document_modified;
doc = xed_tab_get_document (tab); doc = xed_tab_get_document (tab);
g_return_if_fail (XED_IS_DOCUMENT (doc)); g_return_if_fail (XED_IS_DOCUMENT (doc));
/* uri cannot be NULL, we're here because /* we're here because the file we're editing changed on disk */
* the file we're editing changed on disk */ location = xed_document_get_location (doc);
uri = xed_document_get_uri (doc); g_return_if_fail (location != NULL);
g_return_if_fail (uri != NULL);
document_modified = gtk_text_buffer_get_modified (GTK_TEXT_BUFFER(doc)); document_modified = gtk_text_buffer_get_modified (GTK_TEXT_BUFFER(doc));
message_area = xed_externally_modified_message_area_new (uri, document_modified); message_area = xed_externally_modified_message_area_new (location, document_modified);
g_free (uri); g_object_unref (location);
tab->priv->message_area = NULL; tab->priv->message_area = NULL;
set_message_area (tab, message_area); set_message_area (tab, message_area);
@ -1448,8 +1462,8 @@ xed_tab_init (XedTab *tab)
gtk_container_add (GTK_CONTAINER (sw), tab->priv->view); gtk_container_add (GTK_CONTAINER (sw), tab->priv->view);
gtk_widget_show (sw); gtk_widget_show (sw);
g_signal_connect (doc, "notify::uri", g_signal_connect (doc, "notify::location",
G_CALLBACK (document_uri_notify_handler), tab); G_CALLBACK (document_location_notify_handler), tab);
g_signal_connect (doc, "notify::shortname", g_signal_connect (doc, "notify::shortname",
G_CALLBACK (document_shortname_notify_handler), tab); G_CALLBACK (document_shortname_notify_handler), tab);
g_signal_connect (doc, "modified_changed", g_signal_connect (doc, "modified_changed",
@ -1478,18 +1492,18 @@ _xed_tab_new (void)
/* Whether create is TRUE, creates a new empty document if location does /* Whether create is TRUE, creates a new empty document if location does
not refer to an existing file */ not refer to an existing file */
GtkWidget * GtkWidget *
_xed_tab_new_from_uri (const gchar *uri, _xed_tab_new_from_location (GFile *location,
const XedEncoding *encoding, const XedEncoding *encoding,
gint line_pos, gint line_pos,
gboolean create) gboolean create)
{ {
XedTab *tab; XedTab *tab;
g_return_val_if_fail (uri != NULL, NULL); g_return_val_if_fail (G_IS_FILE (location), NULL);
tab = XED_TAB (_xed_tab_new ()); tab = XED_TAB (_xed_tab_new ());
_xed_tab_load (tab, uri, encoding, line_pos, create); _xed_tab_load (tab, location, encoding, line_pos, create);
return GTK_WIDGET (tab); return GTK_WIDGET (tab);
} }
@ -1805,7 +1819,7 @@ xed_tab_get_from_document (XedDocument *doc)
void void
_xed_tab_load (XedTab *tab, _xed_tab_load (XedTab *tab,
const gchar *uri, GFile *location,
const XedEncoding *encoding, const XedEncoding *encoding,
gint line_pos, gint line_pos,
gboolean create) gboolean create)
@ -1813,6 +1827,7 @@ _xed_tab_load (XedTab *tab,
XedDocument *doc; XedDocument *doc;
g_return_if_fail (XED_IS_TAB (tab)); g_return_if_fail (XED_IS_TAB (tab));
g_return_if_fail (G_IS_FILE (location));
g_return_if_fail (tab->priv->state == XED_TAB_STATE_NORMAL); g_return_if_fail (tab->priv->state == XED_TAB_STATE_NORMAL);
doc = xed_tab_get_document (tab); doc = xed_tab_get_document (tab);
@ -1828,14 +1843,14 @@ _xed_tab_load (XedTab *tab,
remove_auto_save_timeout (tab); remove_auto_save_timeout (tab);
} }
xed_document_load (doc, uri, encoding, line_pos, create); xed_document_load (doc, location, encoding, line_pos, create);
} }
void void
_xed_tab_revert (XedTab *tab) _xed_tab_revert (XedTab *tab)
{ {
XedDocument *doc; XedDocument *doc;
gchar *uri; GFile *location;
g_return_if_fail (XED_IS_TAB (tab)); g_return_if_fail (XED_IS_TAB (tab));
g_return_if_fail ((tab->priv->state == XED_TAB_STATE_NORMAL) || g_return_if_fail ((tab->priv->state == XED_TAB_STATE_NORMAL) ||
@ -1851,8 +1866,8 @@ _xed_tab_revert (XedTab *tab)
xed_tab_set_state (tab, XED_TAB_STATE_REVERTING); xed_tab_set_state (tab, XED_TAB_STATE_REVERTING);
uri = xed_document_get_uri (doc); location = xed_document_get_location (doc);
g_return_if_fail (uri != NULL); g_return_if_fail (location != NULL);
tab->priv->tmp_line_pos = 0; tab->priv->tmp_line_pos = 0;
tab->priv->tmp_encoding = xed_document_get_encoding (doc); tab->priv->tmp_encoding = xed_document_get_encoding (doc);
@ -1862,9 +1877,9 @@ _xed_tab_revert (XedTab *tab)
remove_auto_save_timeout (tab); remove_auto_save_timeout (tab);
} }
xed_document_load (doc, uri, tab->priv->tmp_encoding, 0, FALSE); xed_document_load (doc, location, tab->priv->tmp_encoding, 0, FALSE);
g_free (uri); g_object_unref (location);
} }
void void
@ -1877,7 +1892,7 @@ _xed_tab_save (XedTab *tab)
g_return_if_fail ((tab->priv->state == XED_TAB_STATE_NORMAL) || g_return_if_fail ((tab->priv->state == XED_TAB_STATE_NORMAL) ||
(tab->priv->state == XED_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION) || (tab->priv->state == XED_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION) ||
(tab->priv->state == XED_TAB_STATE_SHOWING_PRINT_PREVIEW)); (tab->priv->state == XED_TAB_STATE_SHOWING_PRINT_PREVIEW));
g_return_if_fail (tab->priv->tmp_save_uri == NULL); g_return_if_fail (tab->priv->tmp_save_location == NULL);
g_return_if_fail (tab->priv->tmp_encoding == NULL); g_return_if_fail (tab->priv->tmp_encoding == NULL);
doc = xed_tab_get_document (tab); doc = xed_tab_get_document (tab);
@ -1902,7 +1917,7 @@ _xed_tab_save (XedTab *tab)
xed_tab_set_state (tab, XED_TAB_STATE_SAVING); xed_tab_set_state (tab, XED_TAB_STATE_SAVING);
/* uri used in error messages, will be freed in document_saved */ /* uri used in error messages, will be freed in document_saved */
tab->priv->tmp_save_uri = xed_document_get_uri (doc); tab->priv->tmp_save_location = xed_document_get_location (doc);
tab->priv->tmp_encoding = xed_document_get_encoding (doc); tab->priv->tmp_encoding = xed_document_get_encoding (doc);
if (tab->priv->auto_save_timeout > 0) if (tab->priv->auto_save_timeout > 0)
@ -1920,7 +1935,7 @@ xed_tab_auto_save (XedTab *tab)
xed_debug (DEBUG_TAB); xed_debug (DEBUG_TAB);
g_return_val_if_fail (tab->priv->tmp_save_uri == NULL, FALSE); g_return_val_if_fail (tab->priv->tmp_save_location == NULL, FALSE);
g_return_val_if_fail (tab->priv->tmp_encoding == NULL, FALSE); g_return_val_if_fail (tab->priv->tmp_encoding == NULL, FALSE);
doc = xed_tab_get_document (tab); doc = xed_tab_get_document (tab);
@ -1958,7 +1973,7 @@ xed_tab_auto_save (XedTab *tab)
xed_tab_set_state (tab, XED_TAB_STATE_SAVING); xed_tab_set_state (tab, XED_TAB_STATE_SAVING);
/* uri used in error messages, will be freed in document_saved */ /* uri used in error messages, will be freed in document_saved */
tab->priv->tmp_save_uri = xed_document_get_uri (doc); tab->priv->tmp_save_location = xed_document_get_location (doc);
tab->priv->tmp_encoding = xed_document_get_encoding (doc); tab->priv->tmp_encoding = xed_document_get_encoding (doc);
/* Set auto_save_timeout to 0 since the timeout is going to be destroyed */ /* Set auto_save_timeout to 0 since the timeout is going to be destroyed */
@ -1978,7 +1993,7 @@ xed_tab_auto_save (XedTab *tab)
void void
_xed_tab_save_as (XedTab *tab, _xed_tab_save_as (XedTab *tab,
const gchar *uri, GFile *location,
const XedEncoding *encoding, const XedEncoding *encoding,
XedDocumentNewlineType newline_type) XedDocumentNewlineType newline_type)
{ {
@ -1989,9 +2004,10 @@ _xed_tab_save_as (XedTab *tab,
g_return_if_fail ((tab->priv->state == XED_TAB_STATE_NORMAL) || g_return_if_fail ((tab->priv->state == XED_TAB_STATE_NORMAL) ||
(tab->priv->state == XED_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION) || (tab->priv->state == XED_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION) ||
(tab->priv->state == XED_TAB_STATE_SHOWING_PRINT_PREVIEW)); (tab->priv->state == XED_TAB_STATE_SHOWING_PRINT_PREVIEW));
g_return_if_fail (G_IS_FILE (location));
g_return_if_fail (encoding != NULL); g_return_if_fail (encoding != NULL);
g_return_if_fail (tab->priv->tmp_save_uri == NULL); g_return_if_fail (tab->priv->tmp_save_location == NULL);
g_return_if_fail (tab->priv->tmp_encoding == NULL); g_return_if_fail (tab->priv->tmp_encoding == NULL);
doc = xed_tab_get_document (tab); doc = xed_tab_get_document (tab);
@ -2019,7 +2035,7 @@ _xed_tab_save_as (XedTab *tab,
/* uri used in error messages... strdup because errors are async /* uri used in error messages... strdup because errors are async
* and the string can go away, will be freed in document_saved */ * and the string can go away, will be freed in document_saved */
tab->priv->tmp_save_uri = g_strdup (uri); tab->priv->tmp_save_location = g_file_dup (location);
tab->priv->tmp_encoding = encoding; tab->priv->tmp_encoding = encoding;
if (tab->priv->auto_save_timeout > 0) if (tab->priv->auto_save_timeout > 0)
@ -2032,7 +2048,7 @@ _xed_tab_save_as (XedTab *tab,
a very big deal, but would be nice to have them follow the a very big deal, but would be nice to have them follow the
same pattern. This can be changed once we break API for 3.0 */ same pattern. This can be changed once we break API for 3.0 */
xed_document_set_newline_type (doc, newline_type); xed_document_set_newline_type (doc, newline_type);
xed_document_save_as (doc, uri, encoding, tab->priv->save_flags); xed_document_save_as (doc, location, encoding, tab->priv->save_flags);
} }
#define XED_PAGE_SETUP_KEY "xed-page-setup-key" #define XED_PAGE_SETUP_KEY "xed-page-setup-key"

View File

@ -57,9 +57,6 @@ typedef enum
XED_TAB_NUM_OF_STATES /* This is not a valid state */ XED_TAB_NUM_OF_STATES /* This is not a valid state */
} XedTabState; } XedTabState;
/*
* Type checking and casting macros
*/
#define XED_TYPE_TAB (xed_tab_get_type()) #define XED_TYPE_TAB (xed_tab_get_type())
#define XED_TAB(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), XED_TYPE_TAB, XedTab)) #define XED_TAB(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), XED_TYPE_TAB, XedTab))
#define XED_TAB_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), XED_TYPE_TAB, XedTabClass)) #define XED_TAB_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), XED_TYPE_TAB, XedTabClass))
@ -67,13 +64,9 @@ typedef enum
#define XED_IS_TAB_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XED_TYPE_TAB)) #define XED_IS_TAB_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XED_TYPE_TAB))
#define XED_TAB_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), XED_TYPE_TAB, XedTabClass)) #define XED_TAB_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), XED_TYPE_TAB, XedTabClass))
/* Private structure type */
typedef struct _XedTabPrivate XedTabPrivate;
/*
* Main object structure
*/
typedef struct _XedTab XedTab; typedef struct _XedTab XedTab;
typedef struct _XedTabPrivate XedTabPrivate;
typedef struct _XedTabClass XedTabClass;
struct _XedTab struct _XedTab
{ {
@ -83,43 +76,28 @@ struct _XedTab
XedTabPrivate *priv; XedTabPrivate *priv;
}; };
/*
* Class definition
*/
typedef struct _XedTabClass XedTabClass;
struct _XedTabClass struct _XedTabClass
{ {
GtkBoxClass parent_class; GtkBoxClass parent_class;
}; };
/*
* Public methods
*/
GType xed_tab_get_type (void) G_GNUC_CONST; GType xed_tab_get_type (void) G_GNUC_CONST;
XedView *xed_tab_get_view (XedTab *tab); XedView *xed_tab_get_view (XedTab *tab);
/* This is only an helper function */ /* This is only an helper function */
XedDocument *xed_tab_get_document (XedTab *tab); XedDocument *xed_tab_get_document (XedTab *tab);
XedTab *xed_tab_get_from_document (XedDocument *doc); XedTab *xed_tab_get_from_document (XedDocument *doc);
XedTabState xed_tab_get_state (XedTab *tab); XedTabState xed_tab_get_state (XedTab *tab);
gboolean xed_tab_get_auto_save_enabled gboolean xed_tab_get_auto_save_enabled (XedTab *tab);
(XedTab *tab); void xed_tab_set_auto_save_enabled (XedTab *tab,
void xed_tab_set_auto_save_enabled
(XedTab *tab,
gboolean enable); gboolean enable);
gint xed_tab_get_auto_save_interval gint xed_tab_get_auto_save_interval (XedTab *tab);
(XedTab *tab); void xed_tab_set_auto_save_interval (XedTab *tab,
void xed_tab_set_auto_save_interval
(XedTab *tab,
gint interval); gint interval);
void xed_tab_set_info_bar (XedTab *tab, void xed_tab_set_info_bar (XedTab *tab,
@ -131,7 +109,7 @@ GtkWidget *_xed_tab_new (void);
/* Whether create is TRUE, creates a new empty document if location does /* Whether create is TRUE, creates a new empty document if location does
not refer to an existing file */ not refer to an existing file */
GtkWidget *_xed_tab_new_from_uri (const gchar *uri, GtkWidget *_xed_tab_new_from_location (GFile *location,
const XedEncoding *encoding, const XedEncoding *encoding,
gint line_pos, gint line_pos,
gboolean create); gboolean create);
@ -139,22 +117,20 @@ gchar *_xed_tab_get_name (XedTab *tab);
gchar *_xed_tab_get_tooltips (XedTab *tab); gchar *_xed_tab_get_tooltips (XedTab *tab);
GdkPixbuf *_xed_tab_get_icon (XedTab *tab); GdkPixbuf *_xed_tab_get_icon (XedTab *tab);
void _xed_tab_load (XedTab *tab, void _xed_tab_load (XedTab *tab,
const gchar *uri, GFile *location,
const XedEncoding *encoding, const XedEncoding *encoding,
gint line_pos, gint line_pos,
gboolean create); gboolean create);
void _xed_tab_revert (XedTab *tab); void _xed_tab_revert (XedTab *tab);
void _xed_tab_save (XedTab *tab); void _xed_tab_save (XedTab *tab);
void _xed_tab_save_as (XedTab *tab, void _xed_tab_save_as (XedTab *tab,
const gchar *uri, GFile *location,
const XedEncoding *encoding, const XedEncoding *encoding,
XedDocumentNewlineType newline_type); XedDocumentNewlineType newline_type);
void _xed_tab_print (XedTab *tab); void _xed_tab_print (XedTab *tab);
void _xed_tab_print_preview (XedTab *tab); void _xed_tab_print_preview (XedTab *tab);
void _xed_tab_mark_for_closing (XedTab *tab); void _xed_tab_mark_for_closing (XedTab *tab);
gboolean _xed_tab_can_close (XedTab *tab); gboolean _xed_tab_can_close (XedTab *tab);
G_END_DECLS G_END_DECLS

View File

@ -64,48 +64,12 @@
/** /**
* xed_utils_uris_has_file_scheme * xed_utils_uris_has_file_scheme
* *
* Returns: %TRUE if @uri is a file: uri and is not a chained uri * Returns: %TRUE if @location is a file: uri and is not a chained uri
*/ */
gboolean gboolean
xed_utils_uri_has_file_scheme (const gchar *uri) xed_utils_location_has_file_scheme (GFile *location)
{ {
GFile *gfile; return g_file_has_uri_scheme (location, "file");
gboolean res;
gfile = g_file_new_for_uri (uri);
res = g_file_has_uri_scheme (gfile, "file");
g_object_unref (gfile);
return res;
}
/* FIXME: we should check for chained URIs */
gboolean
xed_utils_uri_has_writable_scheme (const gchar *uri)
{
GFile *gfile;
gchar *scheme;
GSList *writable_schemes;
gboolean res;
gfile = g_file_new_for_uri (uri);
scheme = g_file_get_uri_scheme (gfile);
g_return_val_if_fail (scheme != NULL, FALSE);
g_object_unref (gfile);
writable_schemes = xed_prefs_manager_get_writable_vfs_schemes ();
/* CHECK: should we use g_ascii_strcasecmp? - Paolo (Nov 6, 2005) */
res = (g_slist_find_custom (writable_schemes, scheme, (GCompareFunc)strcmp) != NULL);
g_slist_foreach (writable_schemes, (GFunc)g_free, NULL);
g_slist_free (writable_schemes);
g_free (scheme);
return res;
} }
static void static void
@ -325,19 +289,18 @@ xed_utils_set_atk_relation (GtkWidget *obj1,
} }
gboolean gboolean
xed_utils_uri_exists (const gchar* text_uri) xed_utils_location_exists (GFile *location)
{ {
GFile *gfile;
gboolean res; gboolean res;
gchar *uri;
g_return_val_if_fail (text_uri != NULL, FALSE); g_return_val_if_fail (G_IS_FILE (location), FALSE);
xed_debug_message (DEBUG_UTILS, "text_uri: %s", text_uri); uri = g_file_get_uri (location);
xed_debug_message (DEBUG_UTILS, "text_uri: %s", uri);
g_free (uri);
gfile = g_file_new_for_uri (text_uri); res = g_file_query_exists (location, NULL);
res = g_file_query_exists (gfile, NULL);
g_object_unref (gfile);
xed_debug_message (DEBUG_UTILS, res ? "TRUE" : "FALSE"); xed_debug_message (DEBUG_UTILS, res ? "TRUE" : "FALSE");
@ -1042,20 +1005,27 @@ has_valid_scheme (const gchar *uri)
} }
gboolean gboolean
xed_utils_is_valid_uri (const gchar *uri) xed_utils_is_valid_location (GFile *location)
{ {
const guchar *p; const guchar *p;
gchar *uri;
gboolean is_valid;
if (uri == NULL) if (location == NULL)
{ {
return FALSE; return FALSE;
} }
uri = g_file_get_uri (location);
if (!has_valid_scheme (uri)) if (!has_valid_scheme (uri))
{ {
g_free (uri);
return FALSE; return FALSE;
} }
is_valid = TRUE;
/* We expect to have a fully valid set of characters */ /* We expect to have a fully valid set of characters */
for (p = (const guchar *)uri; *p; p++) for (p = (const guchar *)uri; *p; p++)
{ {
@ -1064,25 +1034,30 @@ xed_utils_is_valid_uri (const gchar *uri)
++p; ++p;
if (!g_ascii_isxdigit (*p)) if (!g_ascii_isxdigit (*p))
{ {
return FALSE; is_valid = FALSE;
break;
} }
++p; ++p;
if (!g_ascii_isxdigit (*p)) if (!g_ascii_isxdigit (*p))
{ {
return FALSE; is_valid = FALSE;
break;
} }
} }
else else
{ {
if (*p <= 32 || *p >= 128) if (*p <= 32 || *p >= 128)
{ {
return FALSE; is_valid = FALSE;
break;
} }
} }
} }
return TRUE; g_free (uri);
return is_valid;
} }
static GtkWidget * static GtkWidget *
@ -1248,15 +1223,15 @@ xed_utils_make_canonical_uri_from_shell_arg (const gchar *str)
*/ */
gfile = g_file_new_for_commandline_arg (str); gfile = g_file_new_for_commandline_arg (str);
if (xed_utils_is_valid_location (gfile))
{
uri = g_file_get_uri (gfile); uri = g_file_get_uri (gfile);
g_object_unref (gfile); g_object_unref (gfile);
if (xed_utils_is_valid_uri (uri))
{
return uri; return uri;
} }
g_free (uri); g_object_unref (gfile);
return NULL; return NULL;
} }
@ -1286,26 +1261,26 @@ xed_utils_file_has_parent (GFile *gfile)
/** /**
* xed_utils_basename_for_display: * xed_utils_basename_for_display:
* @uri: uri for which the basename should be displayed * @location: location for which the basename should be displayed
* *
* Return the basename of a file suitable for display to users. * Return the basename of a file suitable for display to users.
*/ */
gchar * gchar *
xed_utils_basename_for_display (gchar const *uri) xed_utils_basename_for_display (GFile *location)
{ {
gchar *name; gchar *name;
GFile *gfile;
gchar *hn; gchar *hn;
gchar *uri;
g_return_val_if_fail (uri != NULL, NULL); g_return_val_if_fail (G_IS_FILE (location), NULL);
gfile = g_file_new_for_uri (uri); uri = g_file_get_uri (location);
/* First, try to query the display name, but only on local files */ /* First, try to query the display name, but only on local files */
if (g_file_has_uri_scheme (gfile, "file")) if (xed_utils_location_has_file_scheme (location))
{ {
GFileInfo *info; GFileInfo *info;
info = g_file_query_info (gfile, info = g_file_query_info (location,
G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME,
G_FILE_QUERY_INFO_NONE, G_FILE_QUERY_INFO_NONE,
NULL, NULL,
@ -1323,12 +1298,12 @@ xed_utils_basename_for_display (gchar const *uri)
* g_filename_display_basename on the local path */ * g_filename_display_basename on the local path */
gchar *local_path; gchar *local_path;
local_path = g_file_get_path (gfile); local_path = g_file_get_path (location);
name = g_filename_display_basename (local_path); name = g_filename_display_basename (local_path);
g_free (local_path); g_free (local_path);
} }
} }
else if (xed_utils_file_has_parent (gfile) || !xed_utils_decode_uri (uri, NULL, NULL, &hn, NULL, NULL)) else if (xed_utils_file_has_parent (location) || !xed_utils_decode_uri (uri, NULL, NULL, &hn, NULL, NULL))
{ {
/* For remote files with a parent (so not just http://foo.com) /* For remote files with a parent (so not just http://foo.com)
or remote file for which the decoding of the host name fails, or remote file for which the decoding of the host name fails,
@ -1336,7 +1311,7 @@ xed_utils_basename_for_display (gchar const *uri)
gchar *parse_name; gchar *parse_name;
gchar *base; gchar *base;
parse_name = g_file_get_parse_name (gfile); parse_name = g_file_get_parse_name (location);
base = g_filename_display_basename (parse_name); base = g_filename_display_basename (parse_name);
name = g_uri_unescape_string (base, NULL); name = g_uri_unescape_string (base, NULL);
@ -1365,14 +1340,14 @@ xed_utils_basename_for_display (gchar const *uri)
g_free (hn); g_free (hn);
} }
g_object_unref (gfile); g_free (uri);
return name; return name;
} }
/** /**
* xed_utils_uri_for_display: * xed_utils_uri_for_display:
* @uri: uri to be displayed. * @location: location to be displayed.
* *
* Filter, modify, unescape and change @uri to make it appropriate * Filter, modify, unescape and change @uri to make it appropriate
* for display to users. * for display to users.
@ -1382,16 +1357,9 @@ xed_utils_basename_for_display (gchar const *uri)
* Return value: a string which represents @uri and can be displayed. * Return value: a string which represents @uri and can be displayed.
*/ */
gchar * gchar *
xed_utils_uri_for_display (const gchar *uri) xed_utils_uri_for_display (GFile *location)
{ {
GFile *gfile; return g_file_get_parse_name (location);
gchar *parse_name;
gfile = g_file_new_for_uri (uri);
parse_name = g_file_get_parse_name (gfile);
g_object_unref (gfile);
return parse_name;
} }
/** /**

View File

@ -48,8 +48,7 @@ G_BEGIN_DECLS
enum { XED_ALL_WORKSPACES = 0xffffffff }; enum { XED_ALL_WORKSPACES = 0xffffffff };
gboolean xed_utils_uri_has_writable_scheme (const gchar *uri); gboolean xed_utils_location_has_file_scheme (GFile *location);
gboolean xed_utils_uri_has_file_scheme (const gchar *uri);
void xed_utils_menu_position_under_widget (GtkMenu *menu, void xed_utils_menu_position_under_widget (GtkMenu *menu,
gint *x, gint *x,
@ -87,7 +86,7 @@ void xed_utils_set_atk_relation (GtkWidget *obj1,
GtkWidget *obj2, GtkWidget *obj2,
AtkRelationType rel_type); AtkRelationType rel_type);
gboolean xed_utils_uri_exists (const gchar* text_uri); gboolean xed_utils_location_exists (GFile *location);
gchar *xed_utils_escape_search_text (const gchar *text); gchar *xed_utils_escape_search_text (const gchar *text);
@ -114,7 +113,7 @@ void xed_utils_get_current_viewport (GdkScreen *screen,
gint *x, gint *x,
gint *y); gint *y);
gboolean xed_utils_is_valid_uri (const gchar *uri); gboolean xed_utils_is_valid_location (GFile *location);
gboolean xed_utils_get_ui_objects (const gchar *filename, gboolean xed_utils_get_ui_objects (const gchar *filename,
gchar **root_objects, gchar **root_objects,
@ -127,9 +126,9 @@ gboolean xed_utils_file_has_parent (GFile *gfile);
/* Return NULL if str is not a valid URI and/or filename */ /* Return NULL if str is not a valid URI and/or filename */
gchar *xed_utils_make_canonical_uri_from_shell_arg (const gchar *str); gchar *xed_utils_make_canonical_uri_from_shell_arg (const gchar *str);
gchar *xed_utils_uri_for_display (const gchar *uri); gchar *xed_utils_uri_for_display (GFile *location);
gchar *xed_utils_basename_for_display (const gchar *uri); gchar *xed_utils_basename_for_display (GFile *location);
gboolean xed_utils_decode_uri (const gchar *uri, gboolean xed_utils_decode_uri (const gchar *uri,
gchar **scheme, gchar **scheme,

View File

@ -43,14 +43,20 @@
/* Signals */ /* Signals */
enum enum
{ {
TAB_ADDED, TAB_REMOVED, TABS_REORDERED, ACTIVE_TAB_CHANGED, ACTIVE_TAB_STATE_CHANGED, LAST_SIGNAL TAB_ADDED,
TAB_REMOVED,
TABS_REORDERED,
ACTIVE_TAB_CHANGED,
ACTIVE_TAB_STATE_CHANGED,
LAST_SIGNAL
}; };
static guint signals[LAST_SIGNAL] = { 0 }; static guint signals[LAST_SIGNAL] = { 0 };
enum enum
{ {
PROP_0, PROP_STATE PROP_0,
PROP_STATE
}; };
enum enum
@ -842,11 +848,12 @@ update_languages_menu (XedWindow *window)
void void
_xed_recent_add (XedWindow *window, _xed_recent_add (XedWindow *window,
const gchar *uri, GFile *location,
const gchar *mime) const gchar *mime)
{ {
GtkRecentManager *recent_manager; GtkRecentManager *recent_manager;
GtkRecentData *recent_data; GtkRecentData *recent_data;
gchar *uri;
static gchar *groups[2] = { "xed", NULL }; static gchar *groups[2] = { "xed", NULL };
@ -862,8 +869,11 @@ _xed_recent_add (XedWindow *window,
recent_data->groups = groups; recent_data->groups = groups;
recent_data->is_private = FALSE; recent_data->is_private = FALSE;
uri = g_file_get_uri (location);
gtk_recent_manager_add_full (recent_manager, uri, recent_data); gtk_recent_manager_add_full (recent_manager, uri, recent_data);
g_free (uri);
g_free (recent_data->app_exec); g_free (recent_data->app_exec);
g_slice_free(GtkRecentData, recent_data); g_slice_free(GtkRecentData, recent_data);
@ -871,29 +881,32 @@ _xed_recent_add (XedWindow *window,
void void
_xed_recent_remove (XedWindow *window, _xed_recent_remove (XedWindow *window,
const gchar *uri) GFile *location)
{ {
GtkRecentManager *recent_manager; GtkRecentManager *recent_manager;
gchar *uri;
recent_manager = gtk_recent_manager_get_default (); recent_manager = gtk_recent_manager_get_default ();
uri = g_file_get_uri (location);
gtk_recent_manager_remove_item (recent_manager, uri, NULL); gtk_recent_manager_remove_item (recent_manager, uri, NULL);
g_free (uri);
} }
static void static void
open_recent_file (const gchar *uri, open_recent_file (GFile *location,
XedWindow *window) XedWindow *window)
{ {
GSList *uris = NULL; GSList *locations = NULL;
uris = g_slist_prepend (uris, (gpointer) uri); locations = g_slist_prepend (locations, (gpointer) location);
if (xed_commands_load_uris (window, uris, NULL, 0) != 1) if (xed_commands_load_locations (window, locations, NULL, 0) != 1)
{ {
_xed_recent_remove (window, uri); _xed_recent_remove (window, location);
} }
g_slist_free (uris); g_slist_free (locations);
} }
static void static void
@ -901,14 +914,20 @@ recents_menu_activate (GtkAction *action,
XedWindow *window) XedWindow *window)
{ {
GtkRecentInfo *info; GtkRecentInfo *info;
GFile *location;
const gchar *uri; const gchar *uri;
info = g_object_get_data (G_OBJECT (action), "gtk-recent-info"); info = g_object_get_data (G_OBJECT (action), "gtk-recent-info");
g_return_if_fail (info != NULL); g_return_if_fail (info != NULL);
uri = gtk_recent_info_get_uri (info); uri = gtk_recent_info_get_uri (info);
location = g_file_new_for_uri (uri);
open_recent_file (uri, window); if (location)
{
open_recent_file (location, window);
g_object_unref (location);
}
} }
static gint static gint
@ -994,6 +1013,7 @@ update_recent_files_menu (XedWindow *window)
gchar *tip; gchar *tip;
GtkAction *action; GtkAction *action;
GtkRecentInfo *info = l->data; GtkRecentInfo *info = l->data;
GFile *location;
/* clamp */ /* clamp */
if (i >= max_recents) if (i >= max_recents)
@ -1017,7 +1037,9 @@ update_recent_files_menu (XedWindow *window)
/* gtk_recent_info_get_uri_display (info) is buggy and /* gtk_recent_info_get_uri_display (info) is buggy and
* works only for local files */ * works only for local files */
uri = xed_utils_uri_for_display (gtk_recent_info_get_uri (info)); location = g_file_new_for_uri (gtk_recent_info_get_uri (info));
uri = xed_utils_uri_for_display (location);
g_object_unref (location);
ruri = xed_utils_replace_home_dir_with_tilde (uri); ruri = xed_utils_replace_home_dir_with_tilde (uri);
g_free (uri); g_free (uri);
@ -2382,7 +2404,7 @@ static void
load_uris_from_drop (XedWindow *window, load_uris_from_drop (XedWindow *window,
gchar **uri_list) gchar **uri_list)
{ {
GSList *uris = NULL; GSList *locations = NULL;
gint i; gint i;
if (uri_list == NULL) if (uri_list == NULL)
@ -2392,13 +2414,14 @@ load_uris_from_drop (XedWindow *window,
for (i = 0; uri_list[i] != NULL; ++i) for (i = 0; uri_list[i] != NULL; ++i)
{ {
uris = g_slist_prepend (uris, uri_list[i]); locations = g_slist_prepend (locations, g_file_new_for_uri (uri_list[i]));
} }
uris = g_slist_reverse (uris); locations = g_slist_reverse (locations);
xed_commands_load_uris (window, uris, NULL, 0); xed_commands_load_locations (window, locations, NULL, 0);
g_slist_free (uris); g_slist_foreach (locations, (GFunc) g_object_unref, NULL);
g_slist_free (locations);
} }
/* Handle drops on the XedWindow */ /* Handle drops on the XedWindow */
@ -3596,9 +3619,9 @@ xed_window_create_tab (XedWindow *window,
} }
/** /**
* xed_window_create_tab_from_uri: * xed_window_create_tab_from_location:
* @window: a #XedWindow * @window: a #XedWindow
* @uri: the uri of the document * @location: the location of the document
* @encoding: a #XedEncoding * @encoding: a #XedEncoding
* @line_pos: the line position to visualize * @line_pos: the line position to visualize
* @create: %TRUE to create a new document in case @uri does exist * @create: %TRUE to create a new document in case @uri does exist
@ -3612,8 +3635,8 @@ xed_window_create_tab (XedWindow *window,
* Returns: (transfer none): a new #XedTab * Returns: (transfer none): a new #XedTab
*/ */
XedTab * XedTab *
xed_window_create_tab_from_uri (XedWindow *window, xed_window_create_tab_from_location (XedWindow *window,
const gchar *uri, GFile *location,
const XedEncoding *encoding, const XedEncoding *encoding,
gint line_pos, gint line_pos,
gboolean create, gboolean create,
@ -3622,9 +3645,9 @@ xed_window_create_tab_from_uri (XedWindow *window,
GtkWidget *tab; GtkWidget *tab;
g_return_val_if_fail(XED_IS_WINDOW (window), NULL); g_return_val_if_fail(XED_IS_WINDOW (window), NULL);
g_return_val_if_fail(uri != NULL, NULL); g_return_val_if_fail(G_IS_FILE (location), NULL);
tab = _xed_tab_new_from_uri (uri, encoding, line_pos, create); tab = _xed_tab_new_from_location (location, encoding, line_pos, create);
if (tab == NULL) if (tab == NULL)
{ {
return NULL; return NULL;

View File

@ -20,9 +20,6 @@ typedef enum
XED_WINDOW_STATE_SAVING_SESSION = 1 << 5 XED_WINDOW_STATE_SAVING_SESSION = 1 << 5
} XedWindowState; } XedWindowState;
/*
* Type checking and casting macros
*/
#define XED_TYPE_WINDOW (xed_window_get_type()) #define XED_TYPE_WINDOW (xed_window_get_type())
#define XED_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), XED_TYPE_WINDOW, XedWindow)) #define XED_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), XED_TYPE_WINDOW, XedWindow))
#define XED_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), XED_TYPE_WINDOW, XedWindowClass)) #define XED_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), XED_TYPE_WINDOW, XedWindowClass))
@ -30,13 +27,9 @@ typedef enum
#define XED_IS_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XED_TYPE_WINDOW)) #define XED_IS_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XED_TYPE_WINDOW))
#define XED_WINDOW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), XED_TYPE_WINDOW, XedWindowClass)) #define XED_WINDOW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), XED_TYPE_WINDOW, XedWindowClass))
/* Private structure type */
typedef struct _XedWindowPrivate XedWindowPrivate;
/*
* Main object structure
*/
typedef struct _XedWindow XedWindow; typedef struct _XedWindow XedWindow;
typedef struct _XedWindowPrivate XedWindowPrivate;
typedef struct _XedWindowClass XedWindowClass;
struct _XedWindow struct _XedWindow
{ {
@ -46,11 +39,6 @@ struct _XedWindow
XedWindowPrivate *priv; XedWindowPrivate *priv;
}; };
/*
* Class definition
*/
typedef struct _XedWindowClass XedWindowClass;
struct _XedWindowClass struct _XedWindowClass
{ {
GtkWindowClass parent_class; GtkWindowClass parent_class;
@ -68,7 +56,7 @@ struct _XedWindowClass
*/ */
GType xed_window_get_type (void) G_GNUC_CONST; GType xed_window_get_type (void) G_GNUC_CONST;
XedTab *xed_window_create_tab (XedWindow *window, gboolean jump_to); XedTab *xed_window_create_tab (XedWindow *window, gboolean jump_to);
XedTab *xed_window_create_tab_from_uri (XedWindow *window, const gchar *uri, const XedEncoding *encoding, XedTab *xed_window_create_tab_from_location (XedWindow *window, GFile *location, const XedEncoding *encoding,
gint line_pos, gboolean create, gboolean jump_to); gint line_pos, gboolean create, gboolean jump_to);
void xed_window_close_tab (XedWindow *window, XedTab *tab); void xed_window_close_tab (XedWindow *window, XedTab *tab);
void xed_window_close_all_tabs (XedWindow *window); void xed_window_close_all_tabs (XedWindow *window);
@ -115,8 +103,8 @@ void _xed_window_unfullscreen (XedWindow *window);
gboolean _xed_window_is_fullscreen (XedWindow *window); gboolean _xed_window_is_fullscreen (XedWindow *window);
/* these are in xed-window because of screen safety */ /* these are in xed-window because of screen safety */
void _xed_recent_add (XedWindow *window, const gchar *uri, const gchar *mime); void _xed_recent_add (XedWindow *window, GFile *location, const gchar *mime);
void _xed_recent_remove (XedWindow *window, const gchar *uri); void _xed_recent_remove (XedWindow *window, GFile *location);
G_END_DECLS G_END_DECLS