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:
parent
6a997b1b79
commit
f21c6e9361
|
@ -535,6 +535,7 @@ init_bookmarks (XedFileBookmarksStore * model)
|
|||
{
|
||||
if (**line)
|
||||
{
|
||||
GFile *location;
|
||||
gchar *pos;
|
||||
gchar *name;
|
||||
|
||||
|
@ -553,10 +554,12 @@ init_bookmarks (XedFileBookmarksStore * model)
|
|||
|
||||
/* the bookmarks file should contain valid
|
||||
* 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);
|
||||
}
|
||||
g_object_unref (location);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -844,14 +847,14 @@ xed_file_bookmarks_store_new (void)
|
|||
return model;
|
||||
}
|
||||
|
||||
gchar *
|
||||
xed_file_bookmarks_store_get_uri (XedFileBookmarksStore *model,
|
||||
GFile *
|
||||
xed_file_bookmarks_store_get_location (XedFileBookmarksStore *model,
|
||||
GtkTreeIter *iter)
|
||||
{
|
||||
GObject *obj;
|
||||
GFile *file = NULL;
|
||||
guint flags;
|
||||
gchar * ret = NULL;
|
||||
GFile *ret = NULL;
|
||||
gboolean isfs;
|
||||
|
||||
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)
|
||||
{
|
||||
ret = g_file_get_uri (file);
|
||||
ret = g_file_dup (file);
|
||||
g_object_unref (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);
|
||||
|
||||
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);
|
||||
void xed_file_bookmarks_store_refresh (XedFileBookmarksStore * model);
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
VOID:UINT,STRING
|
||||
VOID:STRING,STRING
|
||||
VOID:OBJECT,OBJECT
|
||||
BOOL:OBJECT,POINTER
|
||||
BOOL:POINTER
|
||||
BOOL:VOID
|
||||
|
|
|
@ -178,13 +178,16 @@ message_get_root_cb (XedMessageBus *bus,
|
|||
WindowData *data)
|
||||
{
|
||||
XedFileBrowserStore *store;
|
||||
gchar *uri;
|
||||
GFile *location;
|
||||
|
||||
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);
|
||||
g_free (uri);
|
||||
if (location)
|
||||
{
|
||||
xed_message_set (message, "location", location, NULL);
|
||||
g_object_unref (location);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -192,10 +195,10 @@ message_set_root_cb (XedMessageBus *bus,
|
|||
XedMessage *message,
|
||||
WindowData *data)
|
||||
{
|
||||
gchar *root = NULL;
|
||||
gchar *virtual = NULL;
|
||||
GFile *root;
|
||||
GFile *virtual = NULL;
|
||||
|
||||
xed_message_get (message, "uri", &root, NULL);
|
||||
xed_message_get (message, "location", &root, NULL);
|
||||
|
||||
if (!root)
|
||||
return;
|
||||
|
@ -207,9 +210,6 @@ message_set_root_cb (XedMessageBus *bus,
|
|||
xed_file_browser_widget_set_root_and_virtual_root (data->widget, root, virtual);
|
||||
else
|
||||
xed_file_browser_widget_set_root (data->widget, root, TRUE);
|
||||
|
||||
g_free (root);
|
||||
g_free (virtual);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -278,23 +278,30 @@ message_set_emblem_cb (XedMessageBus *bus,
|
|||
|
||||
static gchar *
|
||||
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 *
|
||||
track_row (WindowData *data,
|
||||
XedFileBrowserStore *store,
|
||||
GtkTreePath *path,
|
||||
const gchar *uri)
|
||||
GFile *location)
|
||||
{
|
||||
GtkTreeRowReference *ref;
|
||||
gchar *id;
|
||||
gchar *pathstr;
|
||||
|
||||
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);
|
||||
g_hash_table_insert (data->row_tracking, g_strdup (id), ref);
|
||||
|
@ -311,28 +318,28 @@ set_item_message (WindowData *data,
|
|||
XedMessage *message)
|
||||
{
|
||||
XedFileBrowserStore *store;
|
||||
gchar *uri = NULL;
|
||||
GFile *location;
|
||||
guint flags = 0;
|
||||
gchar *track_id;
|
||||
|
||||
store = xed_file_browser_widget_get_browser_store (data->widget);
|
||||
|
||||
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,
|
||||
-1);
|
||||
|
||||
if (!uri)
|
||||
if (!location)
|
||||
return;
|
||||
|
||||
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
|
||||
track_id = NULL;
|
||||
|
||||
xed_message_set (message,
|
||||
"id", track_id,
|
||||
"uri", uri,
|
||||
"location", location,
|
||||
NULL);
|
||||
|
||||
if (xed_message_has_key (message, "is_directory"))
|
||||
|
@ -342,7 +349,6 @@ set_item_message (WindowData *data,
|
|||
NULL);
|
||||
}
|
||||
|
||||
g_free (uri);
|
||||
g_free (track_id);
|
||||
}
|
||||
|
||||
|
@ -353,19 +359,18 @@ custom_message_filter_func (XedFileBrowserWidget *widget,
|
|||
FilterData *data)
|
||||
{
|
||||
WindowData *wdata = get_window_data (data->window);
|
||||
gchar *uri = NULL;
|
||||
GFile *location;
|
||||
guint flags = 0;
|
||||
gboolean filter = FALSE;
|
||||
GtkTreePath *path;
|
||||
|
||||
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,
|
||||
-1);
|
||||
|
||||
if (!uri || FILE_IS_DUMMY (flags))
|
||||
if (!location || FILE_IS_DUMMY (flags))
|
||||
{
|
||||
g_free (uri);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -420,7 +425,7 @@ message_add_filter_cb (XedMessageBus *bus,
|
|||
|
||||
// Check if the message type has the correct arguments
|
||||
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, "filter") != G_TYPE_BOOLEAN)
|
||||
{
|
||||
|
@ -429,7 +434,7 @@ message_add_filter_cb (XedMessageBus *bus,
|
|||
|
||||
cbmessage = xed_message_type_instantiate (message_type,
|
||||
"id", NULL,
|
||||
"uri", NULL,
|
||||
"location", NULL,
|
||||
"is_directory", FALSE,
|
||||
"filter", FALSE,
|
||||
NULL);
|
||||
|
@ -647,13 +652,13 @@ register_methods (XedWindow *window,
|
|||
xed_message_bus_register (bus,
|
||||
MESSAGE_OBJECT_PATH, "get_root",
|
||||
1,
|
||||
"uri", G_TYPE_STRING,
|
||||
"location", G_TYPE_FILE,
|
||||
NULL);
|
||||
|
||||
xed_message_bus_register (bus,
|
||||
MESSAGE_OBJECT_PATH, "set_root",
|
||||
1,
|
||||
"uri", G_TYPE_STRING,
|
||||
"location", G_TYPE_FILE,
|
||||
"virtual", G_TYPE_STRING,
|
||||
NULL);
|
||||
|
||||
|
@ -749,11 +754,9 @@ store_row_inserted (XedFileBrowserStore *store,
|
|||
GtkTreeIter *iter,
|
||||
MessageCacheData *data)
|
||||
{
|
||||
gchar *uri = NULL;
|
||||
guint flags = 0;
|
||||
|
||||
gtk_tree_model_get (GTK_TREE_MODEL (store), iter,
|
||||
XED_FILE_BROWSER_STORE_COLUMN_URI, &uri,
|
||||
XED_FILE_BROWSER_STORE_COLUMN_FLAGS, &flags,
|
||||
-1);
|
||||
|
||||
|
@ -764,8 +767,6 @@ store_row_inserted (XedFileBrowserStore *store,
|
|||
set_item_message (wdata, iter, path, data->message);
|
||||
xed_message_bus_send_message_sync (wdata->bus, data->message);
|
||||
}
|
||||
|
||||
g_free (uri);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -774,14 +775,12 @@ store_row_deleted (XedFileBrowserStore *store,
|
|||
MessageCacheData *data)
|
||||
{
|
||||
GtkTreeIter iter;
|
||||
gchar *uri = NULL;
|
||||
guint flags = 0;
|
||||
|
||||
if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (store), &iter, path))
|
||||
return;
|
||||
|
||||
gtk_tree_model_get (GTK_TREE_MODEL (store), &iter,
|
||||
XED_FILE_BROWSER_STORE_COLUMN_URI, &uri,
|
||||
XED_FILE_BROWSER_STORE_COLUMN_FLAGS, &flags,
|
||||
-1);
|
||||
|
||||
|
@ -792,8 +791,6 @@ store_row_deleted (XedFileBrowserStore *store,
|
|||
set_item_message (wdata, &iter, path, data->message);
|
||||
xed_message_bus_send_message_sync (wdata->bus, data->message);
|
||||
}
|
||||
|
||||
g_free (uri);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -802,20 +799,20 @@ store_virtual_root_changed (XedFileBrowserStore *store,
|
|||
MessageCacheData *data)
|
||||
{
|
||||
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;
|
||||
|
||||
xed_message_set (data->message,
|
||||
"uri", uri,
|
||||
"location", vroot,
|
||||
NULL);
|
||||
|
||||
xed_message_bus_send_message_sync (wdata->bus, data->message);
|
||||
|
||||
g_free (uri);
|
||||
g_object_unref (vroot);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -870,28 +867,28 @@ register_signals (XedWindow *window,
|
|||
MESSAGE_OBJECT_PATH, "root_changed",
|
||||
0,
|
||||
"id", G_TYPE_STRING,
|
||||
"uri", G_TYPE_STRING,
|
||||
"location", G_TYPE_FILE,
|
||||
NULL);
|
||||
|
||||
begin_loading_type = xed_message_bus_register (bus,
|
||||
MESSAGE_OBJECT_PATH, "begin_loading",
|
||||
0,
|
||||
"id", G_TYPE_STRING,
|
||||
"uri", G_TYPE_STRING,
|
||||
"location", G_TYPE_FILE,
|
||||
NULL);
|
||||
|
||||
end_loading_type = xed_message_bus_register (bus,
|
||||
MESSAGE_OBJECT_PATH, "end_loading",
|
||||
0,
|
||||
"id", G_TYPE_STRING,
|
||||
"uri", G_TYPE_STRING,
|
||||
"location", G_TYPE_FILE,
|
||||
NULL);
|
||||
|
||||
inserted_type = xed_message_bus_register (bus,
|
||||
MESSAGE_OBJECT_PATH, "inserted",
|
||||
0,
|
||||
"id", G_TYPE_STRING,
|
||||
"uri", G_TYPE_STRING,
|
||||
"location", G_TYPE_FILE,
|
||||
"is_directory", G_TYPE_BOOLEAN,
|
||||
NULL);
|
||||
|
||||
|
@ -899,7 +896,7 @@ register_signals (XedWindow *window,
|
|||
MESSAGE_OBJECT_PATH, "deleted",
|
||||
0,
|
||||
"id", G_TYPE_STRING,
|
||||
"uri", G_TYPE_STRING,
|
||||
"location", G_TYPE_FILE,
|
||||
"is_directory", G_TYPE_BOOLEAN,
|
||||
NULL);
|
||||
|
||||
|
@ -907,7 +904,7 @@ register_signals (XedWindow *window,
|
|||
|
||||
message = xed_message_type_instantiate (inserted_type,
|
||||
"id", NULL,
|
||||
"uri", NULL,
|
||||
"location", NULL,
|
||||
"is_directory", FALSE,
|
||||
NULL);
|
||||
|
||||
|
@ -923,7 +920,7 @@ register_signals (XedWindow *window,
|
|||
|
||||
message = xed_message_type_instantiate (deleted_type,
|
||||
"id", NULL,
|
||||
"uri", NULL,
|
||||
"location", NULL,
|
||||
"is_directory", FALSE,
|
||||
NULL);
|
||||
data->row_deleted_id =
|
||||
|
@ -936,7 +933,7 @@ register_signals (XedWindow *window,
|
|||
|
||||
message = xed_message_type_instantiate (root_changed_type,
|
||||
"id", NULL,
|
||||
"uri", NULL,
|
||||
"location", NULL,
|
||||
NULL);
|
||||
data->root_changed_id =
|
||||
g_signal_connect_data (store,
|
||||
|
@ -948,7 +945,7 @@ register_signals (XedWindow *window,
|
|||
|
||||
message = xed_message_type_instantiate (begin_loading_type,
|
||||
"id", NULL,
|
||||
"uri", NULL,
|
||||
"location", NULL,
|
||||
NULL);
|
||||
data->begin_loading_id =
|
||||
g_signal_connect_data (store,
|
||||
|
@ -960,7 +957,7 @@ register_signals (XedWindow *window,
|
|||
|
||||
message = xed_message_type_instantiate (end_loading_type,
|
||||
"id", NULL,
|
||||
"uri", NULL,
|
||||
"location", NULL,
|
||||
NULL);
|
||||
data->end_loading_id =
|
||||
g_signal_connect_data (store,
|
||||
|
|
|
@ -68,8 +68,8 @@ enum
|
|||
PROP_WINDOW
|
||||
};
|
||||
|
||||
static void on_uri_activated_cb (XedFileBrowserWidget *widget,
|
||||
gchar const *uri,
|
||||
static void on_location_activated_cb (XedFileBrowserWidget *widget,
|
||||
GFile *location,
|
||||
XedWindow *window);
|
||||
static void on_error_cb (XedFileBrowserWidget *widget,
|
||||
guint code,
|
||||
|
@ -85,8 +85,8 @@ static void on_filter_mode_changed_cb (XedFileBrowserStore *model,
|
|||
GParamSpec *param,
|
||||
XedFileBrowserPlugin *plugin);
|
||||
static void on_rename_cb (XedFileBrowserStore *model,
|
||||
const gchar *olduri,
|
||||
const gchar *newuri,
|
||||
GFile *oldfile,
|
||||
GFile *newfile,
|
||||
XedWindow *window);
|
||||
static void on_filter_pattern_changed_cb (XedFileBrowserWidget *widget,
|
||||
GParamSpec *param,
|
||||
|
@ -229,25 +229,28 @@ restore_default_location (XedFileBrowserPlugin *plugin)
|
|||
remote = g_settings_get_boolean (priv->onload_settings, "enable-remote");
|
||||
|
||||
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')
|
||||
{
|
||||
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
|
||||
{
|
||||
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);
|
||||
|
@ -317,16 +320,11 @@ set_root_from_doc (XedFileBrowserPlugin *plugin,
|
|||
|
||||
if (parent != NULL)
|
||||
{
|
||||
gchar * root;
|
||||
|
||||
root = g_file_get_uri (parent);
|
||||
|
||||
xed_file_browser_widget_set_root (priv->tree_widget,
|
||||
root,
|
||||
parent,
|
||||
TRUE);
|
||||
|
||||
g_object_unref (parent);
|
||||
g_free (root);
|
||||
}
|
||||
|
||||
g_object_unref (file);
|
||||
|
@ -352,7 +350,6 @@ on_action_open_terminal (GtkAction *action,
|
|||
{
|
||||
XedFileBrowserPluginPrivate *priv = plugin->priv;
|
||||
gchar *terminal;
|
||||
gchar *wd = NULL;
|
||||
gchar *local;
|
||||
gchar *argv[2];
|
||||
GFile *file;
|
||||
|
@ -367,18 +364,16 @@ on_action_open_terminal (GtkAction *action,
|
|||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
terminal = get_terminal (plugin);
|
||||
|
||||
file = g_file_new_for_uri (wd);
|
||||
local = g_file_get_path (file);
|
||||
g_object_unref (file);
|
||||
|
||||
argv[0] = terminal;
|
||||
argv[1] = NULL;
|
||||
|
@ -393,7 +388,6 @@ on_action_open_terminal (GtkAction *action,
|
|||
NULL);
|
||||
|
||||
g_free (terminal);
|
||||
g_free (wd);
|
||||
g_free (local);
|
||||
}
|
||||
|
||||
|
@ -406,7 +400,7 @@ on_selection_changed_cb (GtkTreeSelection *selection,
|
|||
GtkTreeModel *model;
|
||||
GtkTreeIter iter;
|
||||
gboolean sensitive;
|
||||
gchar *uri;
|
||||
GFile *location;
|
||||
|
||||
tree_view = GTK_TREE_VIEW (xed_file_browser_widget_get_browser_view (priv->tree_widget));
|
||||
model = gtk_tree_view_get_model (tree_view);
|
||||
|
@ -420,10 +414,9 @@ on_selection_changed_cb (GtkTreeSelection *selection,
|
|||
|
||||
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);
|
||||
g_free (uri);
|
||||
sensitive = xed_utils_location_has_file_scheme (location);
|
||||
}
|
||||
|
||||
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->onload_settings = g_settings_new (FILE_BROWSER_ONLOAD_SCHEMA);
|
||||
|
||||
g_signal_connect (priv->tree_widget, "uri-activated",
|
||||
G_CALLBACK (on_uri_activated_cb), priv->window);
|
||||
g_signal_connect (priv->tree_widget, "location-activated",
|
||||
G_CALLBACK (on_location_activated_cb), priv->window);
|
||||
|
||||
g_signal_connect (priv->tree_widget, "error",
|
||||
G_CALLBACK (on_error_cb), plugin);
|
||||
|
@ -652,11 +645,11 @@ xed_file_browser_plugin_class_finalize (XedFileBrowserPluginClass *klass)
|
|||
|
||||
/* Callbacks */
|
||||
static void
|
||||
on_uri_activated_cb (XedFileBrowserWidget *tree_widget,
|
||||
gchar const *uri,
|
||||
on_location_activated_cb (XedFileBrowserWidget *tree_widget,
|
||||
GFile *location,
|
||||
XedWindow *window)
|
||||
{
|
||||
xed_commands_load_uri (window, uri, NULL, 0);
|
||||
xed_commands_load_location (window, location, NULL, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -764,8 +757,8 @@ on_filter_mode_changed_cb (XedFileBrowserStore *model,
|
|||
|
||||
static void
|
||||
on_rename_cb (XedFileBrowserStore *store,
|
||||
const gchar *olduri,
|
||||
const gchar *newuri,
|
||||
GFile *oldfile,
|
||||
GFile *newfile,
|
||||
XedWindow *window)
|
||||
{
|
||||
XedApp *app;
|
||||
|
@ -773,32 +766,24 @@ on_rename_cb (XedFileBrowserStore *store,
|
|||
GList *item;
|
||||
XedDocument *doc;
|
||||
GFile *docfile;
|
||||
GFile *oldfile;
|
||||
GFile *newfile;
|
||||
gchar *uri;
|
||||
|
||||
/* Find all documents and set its uri to newuri where it matches olduri */
|
||||
app = xed_app_get_default ();
|
||||
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)
|
||||
{
|
||||
doc = XED_DOCUMENT (item->data);
|
||||
uri = xed_document_get_uri (doc);
|
||||
docfile = xed_document_get_location (doc);
|
||||
|
||||
if (!uri)
|
||||
if (!docfile)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
docfile = g_file_new_for_uri (uri);
|
||||
|
||||
if (g_file_equal (docfile, oldfile))
|
||||
{
|
||||
xed_document_set_uri (doc, newuri);
|
||||
xed_document_set_location (doc, newfile);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -812,24 +797,18 @@ on_rename_cb (XedFileBrowserStore *store,
|
|||
the prefix oldfile */
|
||||
|
||||
g_object_unref (docfile);
|
||||
g_free (uri);
|
||||
|
||||
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 (uri);
|
||||
g_object_unref (docfile);
|
||||
}
|
||||
|
||||
g_object_unref (oldfile);
|
||||
g_object_unref (newfile);
|
||||
|
||||
g_list_free (documents);
|
||||
}
|
||||
|
||||
|
@ -861,8 +840,9 @@ on_virtual_root_changed_cb (XedFileBrowserStore *store,
|
|||
XedFileBrowserPlugin *plugin)
|
||||
{
|
||||
XedFileBrowserPluginPrivate *priv = plugin->priv;
|
||||
gchar * root;
|
||||
gchar * virtual_root;
|
||||
GFile *root;
|
||||
GFile *virtual_root;
|
||||
gchar *uri_root = NULL;
|
||||
|
||||
root = xed_file_browser_store_get_root (store);
|
||||
|
||||
|
@ -870,25 +850,35 @@ on_virtual_root_changed_cb (XedFileBrowserStore *store,
|
|||
{
|
||||
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);
|
||||
|
||||
if (!virtual_root)
|
||||
{
|
||||
/* 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
|
||||
{
|
||||
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_free (root);
|
||||
g_free (virtual_root);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -905,23 +895,27 @@ on_tab_added_cb (XedWindow *window,
|
|||
if (open)
|
||||
{
|
||||
XedDocument *doc;
|
||||
gchar *uri;
|
||||
GFile *location;
|
||||
|
||||
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);
|
||||
set_root_from_doc (plugin, doc);
|
||||
load_default = FALSE;
|
||||
}
|
||||
|
||||
g_free (uri);
|
||||
g_object_unref (location);
|
||||
}
|
||||
}
|
||||
|
||||
if (load_default)
|
||||
{
|
||||
restore_default_location (plugin);
|
||||
}
|
||||
|
||||
/* Disconnect this signal, it's only called once */
|
||||
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)
|
||||
{
|
||||
GtkTreeIter iter;
|
||||
gchar *uri;
|
||||
GFile *location;
|
||||
|
||||
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
|
||||
|
|
|
@ -81,7 +81,7 @@ struct _AsyncNode
|
|||
|
||||
typedef struct {
|
||||
XedFileBrowserStore *model;
|
||||
gchar *virtual_root;
|
||||
GFile *virtual_root;
|
||||
GMountOperation *operation;
|
||||
GCancellable *cancellable;
|
||||
} MountInfo;
|
||||
|
@ -267,16 +267,13 @@ static void
|
|||
set_gvalue_from_node (GValue *value,
|
||||
FileBrowserNode *node)
|
||||
{
|
||||
gchar * uri;
|
||||
|
||||
if (node == NULL || !node->file)
|
||||
if (node == NULL)
|
||||
{
|
||||
g_value_set_string (value, NULL);
|
||||
g_value_set_object (value, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
uri = g_file_get_uri (node->file);
|
||||
g_value_take_string (value, uri);
|
||||
g_value_set_object (value, node->file);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -335,17 +332,17 @@ xed_file_browser_store_class_init (XedFileBrowserStoreClass * klass)
|
|||
object_class->set_property = xed_file_browser_store_set_property;
|
||||
|
||||
g_object_class_install_property (object_class, PROP_ROOT,
|
||||
g_param_spec_string ("root",
|
||||
g_param_spec_object ("root",
|
||||
"Root",
|
||||
"The root uri",
|
||||
NULL,
|
||||
"The root location",
|
||||
G_TYPE_FILE,
|
||||
G_PARAM_READABLE));
|
||||
|
||||
g_object_class_install_property (object_class, PROP_VIRTUAL_ROOT,
|
||||
g_param_spec_string ("virtual-root",
|
||||
g_param_spec_object ("virtual-root",
|
||||
"Virtual Root",
|
||||
"The virtual root uri",
|
||||
NULL,
|
||||
"The virtual root location",
|
||||
G_TYPE_FILE,
|
||||
G_PARAM_READABLE));
|
||||
|
||||
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_STRUCT_OFFSET (XedFileBrowserStoreClass,
|
||||
rename), NULL, NULL,
|
||||
xed_file_browser_marshal_VOID__STRING_STRING,
|
||||
xed_file_browser_marshal_VOID__OBJECT_OBJECT,
|
||||
G_TYPE_NONE, 2,
|
||||
G_TYPE_STRING,
|
||||
G_TYPE_STRING);
|
||||
G_TYPE_FILE,
|
||||
G_TYPE_FILE);
|
||||
model_signals[BEGIN_REFRESH] =
|
||||
g_signal_new ("begin-refresh",
|
||||
G_OBJECT_CLASS_TYPE (object_class),
|
||||
|
@ -420,9 +417,9 @@ xed_file_browser_store_class_init (XedFileBrowserStoreClass * klass)
|
|||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (XedFileBrowserStoreClass,
|
||||
unload), NULL, NULL,
|
||||
g_cclosure_marshal_VOID__STRING,
|
||||
g_cclosure_marshal_VOID__OBJECT,
|
||||
G_TYPE_NONE, 1,
|
||||
G_TYPE_STRING);
|
||||
G_TYPE_FILE);
|
||||
|
||||
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->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_FLAGS] = G_TYPE_UINT;
|
||||
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)
|
||||
{
|
||||
case XED_FILE_BROWSER_STORE_COLUMN_URI:
|
||||
case XED_FILE_BROWSER_STORE_COLUMN_LOCATION:
|
||||
set_gvalue_from_node (value, node);
|
||||
break;
|
||||
case XED_FILE_BROWSER_STORE_COLUMN_NAME:
|
||||
|
@ -1013,7 +1010,7 @@ xed_file_browser_store_drag_data_get (GtkTreeDragSource *drag_source,
|
|||
GtkSelectionData *selection_data)
|
||||
{
|
||||
GtkTreeIter iter;
|
||||
gchar *uri;
|
||||
GFile *location;
|
||||
gchar *uris[2] = {0, };
|
||||
gboolean ret;
|
||||
|
||||
|
@ -1022,14 +1019,14 @@ xed_file_browser_store_drag_data_get (GtkTreeDragSource *drag_source,
|
|||
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);
|
||||
|
||||
g_free (uri);
|
||||
g_free (uris[0]);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -1448,8 +1445,6 @@ static void
|
|||
file_browser_node_free (XedFileBrowserStore *model,
|
||||
FileBrowserNode *node)
|
||||
{
|
||||
gchar *uri;
|
||||
|
||||
if (node == NULL)
|
||||
{
|
||||
return;
|
||||
|
@ -1485,10 +1480,7 @@ file_browser_node_free (XedFileBrowserStore *model,
|
|||
|
||||
if (node->file)
|
||||
{
|
||||
uri = g_file_get_uri (node->file);
|
||||
g_signal_emit (model, model_signals[UNLOAD], 0, uri);
|
||||
|
||||
g_free (uri);
|
||||
g_signal_emit (model, model_signals[UNLOAD], 0, node->file);
|
||||
g_object_unref (node->file);
|
||||
}
|
||||
|
||||
|
@ -2940,14 +2932,14 @@ unique_new_name (GFile *directory,
|
|||
|
||||
static XedFileBrowserStoreResult
|
||||
model_root_mounted (XedFileBrowserStore *model,
|
||||
gchar const *virtual_root)
|
||||
GFile *virtual_root)
|
||||
{
|
||||
model_check_dummy (model, model->priv->root);
|
||||
g_object_notify (G_OBJECT (model), "root");
|
||||
|
||||
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
|
||||
{
|
||||
|
@ -3028,7 +3020,7 @@ mount_cb (GFile *file,
|
|||
|
||||
static XedFileBrowserStoreResult
|
||||
model_mount_root (XedFileBrowserStore *model,
|
||||
gchar const *virtual_root)
|
||||
GFile *virtual_root)
|
||||
{
|
||||
GFileInfo *info;
|
||||
GError *error = NULL;
|
||||
|
@ -3049,7 +3041,7 @@ model_mount_root (XedFileBrowserStore *model,
|
|||
|
||||
mount_info = g_new(MountInfo, 1);
|
||||
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 */
|
||||
mount_info->operation = gtk_mount_operation_new (NULL);
|
||||
|
@ -3085,7 +3077,7 @@ model_mount_root (XedFileBrowserStore *model,
|
|||
|
||||
/* Public */
|
||||
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));
|
||||
|
||||
|
@ -3156,56 +3148,52 @@ xed_file_browser_store_set_virtual_root (XedFileBrowserStore *model,
|
|||
}
|
||||
|
||||
XedFileBrowserStoreResult
|
||||
xed_file_browser_store_set_virtual_root_from_string (XedFileBrowserStore *model,
|
||||
gchar const *root)
|
||||
xed_file_browser_store_set_virtual_root_from_location (XedFileBrowserStore *model,
|
||||
GFile *root)
|
||||
{
|
||||
GFile *file;
|
||||
|
||||
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 (file == NULL)
|
||||
if (root == 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;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
model_clear (model, FALSE);
|
||||
set_virtual_root_from_node (model, model->priv->root);
|
||||
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;
|
||||
|
||||
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_free (str);
|
||||
g_free (str1);
|
||||
|
||||
g_object_unref (file);
|
||||
return XED_FILE_BROWSER_STORE_RESULT_ERROR;
|
||||
}
|
||||
|
||||
set_virtual_root_from_file (model, file);
|
||||
g_object_unref (file);
|
||||
set_virtual_root_from_file (model, root);
|
||||
|
||||
return XED_FILE_BROWSER_STORE_RESULT_OK;
|
||||
}
|
||||
|
@ -3298,11 +3286,9 @@ xed_file_browser_store_cancel_mount_operation (XedFileBrowserStore *store)
|
|||
|
||||
XedFileBrowserStoreResult
|
||||
xed_file_browser_store_set_root_and_virtual_root (XedFileBrowserStore *model,
|
||||
gchar const *root,
|
||||
gchar const *virtual_root)
|
||||
GFile *root,
|
||||
GFile *virtual_root)
|
||||
{
|
||||
GFile * file = NULL;
|
||||
GFile * vfile = NULL;
|
||||
FileBrowserNode * node;
|
||||
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;
|
||||
}
|
||||
|
||||
if (root != NULL)
|
||||
{
|
||||
file = g_file_new_for_uri (root);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
g_object_unref (file);
|
||||
return XED_FILE_BROWSER_STORE_RESULT_NO_CHANGE;
|
||||
}
|
||||
}
|
||||
|
||||
if (virtual_root)
|
||||
{
|
||||
vfile = g_file_new_for_uri (virtual_root);
|
||||
|
||||
if (equal && g_file_equal (vfile, model->priv->virtual_root->file))
|
||||
if (equal && g_file_equal (virtual_root, model->priv->virtual_root->file))
|
||||
{
|
||||
if (file)
|
||||
{
|
||||
g_object_unref (file);
|
||||
}
|
||||
|
||||
g_object_unref (vfile);
|
||||
return XED_FILE_BROWSER_STORE_RESULT_NO_CHANGE;
|
||||
}
|
||||
|
||||
g_object_unref (vfile);
|
||||
}
|
||||
|
||||
/* 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->virtual_root = NULL;
|
||||
|
||||
if (file != NULL)
|
||||
if (root != NULL)
|
||||
{
|
||||
/* Create the root node */
|
||||
node = file_browser_node_dir_new (model, file, NULL);
|
||||
|
||||
g_object_unref (file);
|
||||
node = file_browser_node_dir_new (model, root, NULL);
|
||||
|
||||
model->priv->root = node;
|
||||
return model_mount_root (model, virtual_root);
|
||||
|
@ -3378,13 +3346,13 @@ xed_file_browser_store_set_root_and_virtual_root (XedFileBrowserStore *model,
|
|||
|
||||
XedFileBrowserStoreResult
|
||||
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);
|
||||
return xed_file_browser_store_set_root_and_virtual_root (model, root, NULL);
|
||||
}
|
||||
|
||||
gchar *
|
||||
GFile *
|
||||
xed_file_browser_store_get_root (XedFileBrowserStore * model)
|
||||
{
|
||||
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
|
||||
{
|
||||
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)
|
||||
{
|
||||
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
|
||||
{
|
||||
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 *previous;
|
||||
GError *err = NULL;
|
||||
gchar *olduri;
|
||||
gchar *newuri;
|
||||
GtkTreePath *path;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
olduri = g_file_get_uri (previous);
|
||||
newuri = g_file_get_uri (node->file);
|
||||
|
||||
g_signal_emit (model, model_signals[RENAME], 0, olduri, newuri);
|
||||
g_signal_emit (model, model_signals[RENAME], 0, previous, node->file);
|
||||
|
||||
g_object_unref (previous);
|
||||
g_free (olduri);
|
||||
g_free (newuri);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ typedef enum
|
|||
{
|
||||
XED_FILE_BROWSER_STORE_COLUMN_ICON = 0,
|
||||
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_EMBLEM,
|
||||
XED_FILE_BROWSER_STORE_COLUMN_NUM
|
||||
|
@ -106,28 +106,28 @@ struct _XedFileBrowserStoreClass {
|
|||
gboolean (*no_trash) (XedFileBrowserStore *model,
|
||||
GList *files);
|
||||
void (*rename) (XedFileBrowserStore *model,
|
||||
const gchar *olduri,
|
||||
const gchar *newuri);
|
||||
GFile *oldfile,
|
||||
GFile *newfile);
|
||||
void (*begin_refresh) (XedFileBrowserStore *model);
|
||||
void (*end_refresh) (XedFileBrowserStore *model);
|
||||
void (*unload) (XedFileBrowserStore *model,
|
||||
const gchar *uri);
|
||||
GFile *location);
|
||||
};
|
||||
|
||||
GType xed_file_browser_store_get_type (void) G_GNUC_CONST;
|
||||
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,
|
||||
gchar const *root,
|
||||
gchar const *virtual_root);
|
||||
GFile *root,
|
||||
GFile *virtual_root);
|
||||
XedFileBrowserStoreResult xed_file_browser_store_set_root (XedFileBrowserStore *model,
|
||||
gchar const *root);
|
||||
GFile *root);
|
||||
XedFileBrowserStoreResult xed_file_browser_store_set_virtual_root (XedFileBrowserStore *model,
|
||||
GtkTreeIter *iter);
|
||||
XedFileBrowserStoreResult xed_file_browser_store_set_virtual_root_from_string (XedFileBrowserStore *model,
|
||||
gchar const *root);
|
||||
XedFileBrowserStoreResult xed_file_browser_store_set_virtual_root_from_location (XedFileBrowserStore *model,
|
||||
GFile *root);
|
||||
XedFileBrowserStoreResult xed_file_browser_store_set_virtual_root_up (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);
|
||||
gboolean xed_file_browser_store_get_iter_root (XedFileBrowserStore *model,
|
||||
GtkTreeIter *iter);
|
||||
gchar * xed_file_browser_store_get_root (XedFileBrowserStore *model);
|
||||
gchar * xed_file_browser_store_get_virtual_root (XedFileBrowserStore *model);
|
||||
GFile * xed_file_browser_store_get_root (XedFileBrowserStore *model);
|
||||
GFile * xed_file_browser_store_get_virtual_root (XedFileBrowserStore *model);
|
||||
|
||||
gboolean xed_file_browser_store_iter_equal (XedFileBrowserStore *model,
|
||||
GtkTreeIter *iter1,
|
||||
|
|
|
@ -128,20 +128,7 @@ xed_file_browser_utils_pixbuf_from_file (GFile * file,
|
|||
gchar *
|
||||
xed_file_browser_utils_file_basename (GFile * file)
|
||||
{
|
||||
gchar *uri;
|
||||
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);
|
||||
return xed_utils_basename_for_display (file);
|
||||
}
|
||||
|
||||
gboolean
|
||||
|
|
|
@ -13,7 +13,6 @@ GdkPixbuf *xed_file_browser_utils_pixbuf_from_file (GFile * file,
|
|||
GtkIconSize size);
|
||||
|
||||
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,
|
||||
GtkMessageType type,
|
||||
|
|
|
@ -99,7 +99,7 @@ static void on_end_refresh (XedFileBrowserStore *model,
|
|||
XedFileBrowserView *view);
|
||||
|
||||
static void on_unload (XedFileBrowserStore *model,
|
||||
gchar const *uri,
|
||||
GFile *location,
|
||||
XedFileBrowserView *view);
|
||||
|
||||
static void on_row_inserted (XedFileBrowserStore *model,
|
||||
|
@ -135,46 +135,32 @@ xed_file_browser_view_finalize (GObject *object)
|
|||
|
||||
static void
|
||||
add_expand_state (XedFileBrowserView *view,
|
||||
gchar const *uri)
|
||||
GFile *location)
|
||||
{
|
||||
GFile * file;
|
||||
|
||||
if (!uri)
|
||||
if (!location)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
file = g_file_new_for_uri (uri);
|
||||
|
||||
if (view->priv->expand_state)
|
||||
{
|
||||
g_hash_table_insert (view->priv->expand_state, file, file);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_object_unref (file);
|
||||
g_hash_table_insert (view->priv->expand_state, location, g_object_ref (location));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
remove_expand_state (XedFileBrowserView *view,
|
||||
gchar const *uri)
|
||||
GFile *location)
|
||||
{
|
||||
GFile * file;
|
||||
|
||||
if (!uri)
|
||||
if (!location)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
file = g_file_new_for_uri (uri);
|
||||
|
||||
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
|
||||
|
@ -183,7 +169,7 @@ row_expanded (GtkTreeView *tree_view,
|
|||
GtkTreePath *path)
|
||||
{
|
||||
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)
|
||||
{
|
||||
|
@ -197,10 +183,9 @@ row_expanded (GtkTreeView *tree_view,
|
|||
|
||||
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);
|
||||
g_free (uri);
|
||||
add_expand_state (view, location);
|
||||
}
|
||||
|
||||
_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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
|
@ -226,10 +211,9 @@ row_collapsed (GtkTreeView *tree_view,
|
|||
|
||||
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);
|
||||
g_free (uri);
|
||||
remove_expand_state (view, location);
|
||||
}
|
||||
|
||||
_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;
|
||||
GtkTreeIter child;
|
||||
gchar * uri;
|
||||
GFile *location;
|
||||
|
||||
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,
|
||||
iter,
|
||||
XED_FILE_BROWSER_STORE_COLUMN_URI,
|
||||
&uri,
|
||||
XED_FILE_BROWSER_STORE_COLUMN_LOCATION,
|
||||
&location,
|
||||
-1);
|
||||
|
||||
add_expand_state (view, uri);
|
||||
g_free (uri);
|
||||
add_expand_state (view, location);
|
||||
}
|
||||
|
||||
if (gtk_tree_model_iter_children (view->priv->model, &child, iter))
|
||||
|
@ -1273,7 +1256,7 @@ on_end_refresh (XedFileBrowserStore *model,
|
|||
|
||||
static void
|
||||
on_unload (XedFileBrowserStore *model,
|
||||
gchar const *uri,
|
||||
GFile *location,
|
||||
XedFileBrowserView *view)
|
||||
{
|
||||
/* Don't remove the expand state if we are refreshing */
|
||||
|
@ -1282,7 +1265,7 @@ on_unload (XedFileBrowserStore *model,
|
|||
return;
|
||||
}
|
||||
|
||||
remove_expand_state (view, uri);
|
||||
remove_expand_state (view, location);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1290,33 +1273,28 @@ restore_expand_state (XedFileBrowserView *view,
|
|||
XedFileBrowserStore *model,
|
||||
GtkTreeIter *iter)
|
||||
{
|
||||
gchar *uri;
|
||||
GFile *file;
|
||||
GFile *location;
|
||||
GtkTreePath *path;
|
||||
|
||||
gtk_tree_model_get (GTK_TREE_MODEL (model),
|
||||
iter,
|
||||
XED_FILE_BROWSER_STORE_COLUMN_URI,
|
||||
&uri,
|
||||
XED_FILE_BROWSER_STORE_COLUMN_LOCATION,
|
||||
&location,
|
||||
-1);
|
||||
|
||||
if (!uri)
|
||||
if (!location)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
file = g_file_new_for_uri (uri);
|
||||
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_path_free (path);
|
||||
|
||||
g_object_unref (file);
|
||||
g_free (uri);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -80,7 +80,7 @@ enum
|
|||
/* Signals */
|
||||
enum
|
||||
{
|
||||
URI_ACTIVATED,
|
||||
LOCATION_ACTIVATED,
|
||||
ERROR,
|
||||
CONFIRM_DELETE,
|
||||
CONFIRM_NO_TRASH,
|
||||
|
@ -433,14 +433,14 @@ xed_file_browser_widget_class_init (XedFileBrowserWidgetClass * klass)
|
|||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT));
|
||||
|
||||
signals[URI_ACTIVATED] =
|
||||
g_signal_new ("uri-activated",
|
||||
signals[LOCATION_ACTIVATED] =
|
||||
g_signal_new ("location-activated",
|
||||
G_OBJECT_CLASS_TYPE (object_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (XedFileBrowserWidgetClass,
|
||||
uri_activated), NULL, NULL,
|
||||
g_cclosure_marshal_VOID__STRING, G_TYPE_NONE, 1,
|
||||
G_TYPE_STRING);
|
||||
location_activated), NULL, NULL,
|
||||
g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1,
|
||||
G_TYPE_FILE);
|
||||
signals[ERROR] =
|
||||
g_signal_new ("error", G_OBJECT_CLASS_TYPE (object_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
|
@ -1060,22 +1060,18 @@ add_bookmark_hash (XedFileBrowserWidget * obj,
|
|||
GtkTreeModel *model;
|
||||
GdkPixbuf * pixbuf;
|
||||
gchar * name;
|
||||
gchar * uri;
|
||||
GFile * file;
|
||||
GFile * location;
|
||||
NameIcon * item;
|
||||
|
||||
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,
|
||||
iter);
|
||||
|
||||
if (uri == NULL)
|
||||
if (location == NULL)
|
||||
return;
|
||||
|
||||
file = g_file_new_for_uri (uri);
|
||||
g_free (uri);
|
||||
|
||||
gtk_tree_model_get (model, iter,
|
||||
XED_FILE_BOOKMARKS_STORE_COLUMN_ICON,
|
||||
&pixbuf,
|
||||
|
@ -1087,7 +1083,7 @@ add_bookmark_hash (XedFileBrowserWidget * obj,
|
|||
item->icon = pixbuf;
|
||||
|
||||
g_hash_table_insert (obj->priv->bookmarks_hash,
|
||||
file,
|
||||
location,
|
||||
item);
|
||||
}
|
||||
|
||||
|
@ -1581,8 +1577,6 @@ jump_to_location (XedFileBrowserWidget * obj, GList * item,
|
|||
GList *(*iter_func) (GList *);
|
||||
GtkWidget *menu_from;
|
||||
GtkWidget *menu_to;
|
||||
gchar *root;
|
||||
gchar *virtual_root;
|
||||
|
||||
if (!obj->priv->locations)
|
||||
return;
|
||||
|
@ -1643,15 +1637,9 @@ jump_to_location (XedFileBrowserWidget * obj, GList * item,
|
|||
loc = (Location *) (obj->priv->current_location->data);
|
||||
|
||||
/* 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,
|
||||
root,
|
||||
virtual_root);
|
||||
|
||||
g_free (root);
|
||||
g_free (virtual_root);
|
||||
loc->root,
|
||||
loc->virtual_root);
|
||||
|
||||
obj->priv->changing_location = FALSE;
|
||||
}
|
||||
|
@ -1840,8 +1828,8 @@ xed_file_browser_widget_show_files (XedFileBrowserWidget * obj)
|
|||
|
||||
void
|
||||
xed_file_browser_widget_set_root_and_virtual_root (XedFileBrowserWidget *obj,
|
||||
gchar const *root,
|
||||
gchar const *virtual_root)
|
||||
GFile *root,
|
||||
GFile *virtual_root)
|
||||
{
|
||||
XedFileBrowserStoreResult result;
|
||||
|
||||
|
@ -1860,12 +1848,10 @@ xed_file_browser_widget_set_root_and_virtual_root (XedFileBrowserWidget *obj,
|
|||
|
||||
void
|
||||
xed_file_browser_widget_set_root (XedFileBrowserWidget * obj,
|
||||
gchar const *root,
|
||||
GFile *root,
|
||||
gboolean virtual_root)
|
||||
{
|
||||
GFile *file;
|
||||
GFile *parent;
|
||||
gchar *str;
|
||||
|
||||
if (!virtual_root) {
|
||||
xed_file_browser_widget_set_root_and_virtual_root (obj,
|
||||
|
@ -1877,16 +1863,11 @@ xed_file_browser_widget_set_root (XedFileBrowserWidget * obj,
|
|||
if (!root)
|
||||
return;
|
||||
|
||||
file = g_file_new_for_uri (root);
|
||||
parent = get_topmost_file (file);
|
||||
str = g_file_get_uri (parent);
|
||||
parent = get_topmost_file (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);
|
||||
}
|
||||
|
||||
|
@ -2113,7 +2094,6 @@ activate_mount (XedFileBrowserWidget *widget,
|
|||
GMount *mount)
|
||||
{
|
||||
GFile *root;
|
||||
gchar *uri;
|
||||
|
||||
if (!mount)
|
||||
{
|
||||
|
@ -2135,11 +2115,9 @@ activate_mount (XedFileBrowserWidget *widget,
|
|||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -2370,7 +2348,7 @@ bookmark_open (XedFileBrowserWidget *obj,
|
|||
GtkTreeModel *model,
|
||||
GtkTreeIter *iter)
|
||||
{
|
||||
gchar *uri;
|
||||
GFile *location;
|
||||
gint flags;
|
||||
|
||||
gtk_tree_model_get (model, iter,
|
||||
|
@ -2392,11 +2370,11 @@ bookmark_open (XedFileBrowserWidget *obj,
|
|||
return;
|
||||
}
|
||||
|
||||
uri =
|
||||
xed_file_bookmarks_store_get_uri
|
||||
location =
|
||||
xed_file_bookmarks_store_get_location
|
||||
(XED_FILE_BOOKMARKS_STORE (model), iter);
|
||||
|
||||
if (uri) {
|
||||
if (location) {
|
||||
/* 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
|
||||
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) ||
|
||||
(flags & XED_FILE_BOOKMARKS_STORE_IS_REMOTE_BOOKMARK)) {
|
||||
xed_file_browser_widget_set_root (obj,
|
||||
uri,
|
||||
location,
|
||||
FALSE);
|
||||
} else {
|
||||
xed_file_browser_widget_set_root (obj,
|
||||
uri,
|
||||
location,
|
||||
TRUE);
|
||||
}
|
||||
|
||||
g_object_unref (location);
|
||||
} else {
|
||||
g_warning ("No uri!");
|
||||
}
|
||||
|
||||
g_free (uri);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -2424,19 +2402,17 @@ file_open (XedFileBrowserWidget *obj,
|
|||
GtkTreeModel *model,
|
||||
GtkTreeIter *iter)
|
||||
{
|
||||
gchar *uri;
|
||||
GFile *location;
|
||||
gint flags;
|
||||
|
||||
gtk_tree_model_get (model, iter,
|
||||
XED_FILE_BROWSER_STORE_COLUMN_FLAGS, &flags,
|
||||
XED_FILE_BROWSER_STORE_COLUMN_URI, &uri,
|
||||
XED_FILE_BROWSER_STORE_COLUMN_LOCATION, &location,
|
||||
-1);
|
||||
|
||||
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
|
||||
|
@ -2446,17 +2422,20 @@ directory_open (XedFileBrowserWidget *obj,
|
|||
{
|
||||
gboolean result = FALSE;
|
||||
GError *error = NULL;
|
||||
gchar *uri = NULL;
|
||||
GFile *location;
|
||||
XedFileBrowserStoreFlag flags;
|
||||
|
||||
gtk_tree_model_get (model, iter,
|
||||
XED_FILE_BROWSER_STORE_COLUMN_FLAGS, &flags,
|
||||
XED_FILE_BROWSER_STORE_COLUMN_URI, &uri,
|
||||
XED_FILE_BROWSER_STORE_COLUMN_LOCATION, &location,
|
||||
-1);
|
||||
|
||||
if (FILE_IS_DIR (flags)) {
|
||||
if (FILE_IS_DIR (flags) && location) {
|
||||
gchar *uri;
|
||||
result = TRUE;
|
||||
|
||||
uri = g_file_get_uri (location);
|
||||
|
||||
if (!gtk_show_uri (gtk_widget_get_screen (GTK_WIDGET (obj)), uri, GDK_CURRENT_TIME, &error)) {
|
||||
g_signal_emit (obj, signals[ERROR], 0,
|
||||
XED_FILE_BROWSER_ERROR_OPEN_DIRECTORY,
|
||||
|
@ -2465,9 +2444,9 @@ directory_open (XedFileBrowserWidget *obj,
|
|||
g_error_free (error);
|
||||
error = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
g_free (uri);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -2514,8 +2493,7 @@ on_virtual_root_changed (XedFileBrowserStore * model,
|
|||
XedFileBrowserWidget * obj)
|
||||
{
|
||||
GtkTreeIter iter;
|
||||
gchar *uri;
|
||||
gchar *root_uri;
|
||||
GFile *location;
|
||||
GtkTreeIter root;
|
||||
GtkAction *action;
|
||||
Location *loc;
|
||||
|
@ -2529,8 +2507,8 @@ on_virtual_root_changed (XedFileBrowserStore * model,
|
|||
|
||||
if (xed_file_browser_store_get_iter_virtual_root (model, &iter)) {
|
||||
gtk_tree_model_get (GTK_TREE_MODEL (model), &iter,
|
||||
XED_FILE_BROWSER_STORE_COLUMN_URI,
|
||||
&uri, -1);
|
||||
XED_FILE_BROWSER_STORE_COLUMN_LOCATION,
|
||||
&location, -1);
|
||||
|
||||
if (xed_file_browser_store_get_iter_root (model, &root)) {
|
||||
if (!obj->priv->changing_location) {
|
||||
|
@ -2538,14 +2516,9 @@ on_virtual_root_changed (XedFileBrowserStore * model,
|
|||
if (obj->priv->current_location)
|
||||
clear_next_locations (obj);
|
||||
|
||||
root_uri =
|
||||
xed_file_browser_store_get_root
|
||||
(model);
|
||||
|
||||
loc = g_new (Location, 1);
|
||||
loc->root = g_file_new_for_uri (root_uri);
|
||||
loc->virtual_root = g_file_new_for_uri (uri);
|
||||
g_free (root_uri);
|
||||
loc->root = xed_file_browser_store_get_root (model);
|
||||
loc->virtual_root = g_object_ref (location);
|
||||
|
||||
if (obj->priv->current_location) {
|
||||
/* 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);
|
||||
g_free (uri);
|
||||
} else {
|
||||
g_message ("NO!");
|
||||
}
|
||||
|
@ -2694,7 +2666,6 @@ on_combo_changed (GtkComboBox * combo, XedFileBrowserWidget * obj)
|
|||
{
|
||||
GtkTreeIter iter;
|
||||
guint id;
|
||||
gchar * uri;
|
||||
GFile * file;
|
||||
|
||||
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,
|
||||
COLUMN_FILE, &file, -1);
|
||||
|
||||
uri = g_file_get_uri (file);
|
||||
xed_file_browser_store_set_virtual_root_from_string
|
||||
(obj->priv->file_store, uri);
|
||||
xed_file_browser_store_set_virtual_root_from_location (obj->priv->file_store, file);
|
||||
|
||||
g_free (uri);
|
||||
g_object_unref (file);
|
||||
break;
|
||||
}
|
||||
|
@ -2902,22 +2870,19 @@ on_bookmarks_row_deleted (GtkTreeModel * model,
|
|||
XedFileBrowserWidget *obj)
|
||||
{
|
||||
GtkTreeIter iter;
|
||||
gchar * uri;
|
||||
GFile * file;
|
||||
GFile *location;
|
||||
|
||||
if (!gtk_tree_model_get_iter (model, &iter, path))
|
||||
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;
|
||||
|
||||
file = g_file_new_for_uri (uri);
|
||||
g_hash_table_remove (obj->priv->bookmarks_hash, file);
|
||||
g_hash_table_remove (obj->priv->bookmarks_hash, location);
|
||||
|
||||
g_object_unref (file);
|
||||
g_free (uri);
|
||||
g_object_unref (location);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -58,8 +58,8 @@ struct _XedFileBrowserWidgetClass
|
|||
GtkBoxClass parent_class;
|
||||
|
||||
/* Signals */
|
||||
void (*uri_activated) (XedFileBrowserWidget * widget,
|
||||
gchar const *uri);
|
||||
void (*location_activated) (XedFileBrowserWidget * widget,
|
||||
GFile *location);
|
||||
void (*error) (XedFileBrowserWidget * widget,
|
||||
guint code,
|
||||
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_set_root (XedFileBrowserWidget * obj,
|
||||
gchar const *root,
|
||||
GFile *root,
|
||||
gboolean virtual_root);
|
||||
void
|
||||
xed_file_browser_widget_set_root_and_virtual_root (XedFileBrowserWidget * obj,
|
||||
gchar const *root,
|
||||
gchar const *virtual_root);
|
||||
GFile *root,
|
||||
GFile *virtual_root);
|
||||
|
||||
gboolean
|
||||
xed_file_browser_widget_get_selected_directory (XedFileBrowserWidget * obj,
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "xed-gio-document-loader.h"
|
||||
#include "xed-document-loader.h"
|
||||
#include "xed-prefs-manager-app.h"
|
||||
#include <gio/gio.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "xed-gio-document-loader.h"
|
||||
#include "xed-document-loader.h"
|
||||
#include "xed-prefs-manager-app.h"
|
||||
#include <gio/gio.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
|
|
@ -51,8 +51,6 @@ NOINST_H_FILES = \
|
|||
xed-document-output-stream.h \
|
||||
xed-document-saver.h \
|
||||
xed-documents-panel.h \
|
||||
xed-gio-document-loader.h \
|
||||
xed-gio-document-saver.h \
|
||||
xed-history-entry.h \
|
||||
xed-io-error-message-area.h \
|
||||
xed-language-manager.h \
|
||||
|
@ -123,9 +121,7 @@ libxed_c_files = \
|
|||
xed-document-input-stream.c \
|
||||
xed-document-loader.c \
|
||||
xed-document-output-stream.c \
|
||||
xed-gio-document-loader.c \
|
||||
xed-document-saver.c \
|
||||
xed-gio-document-saver.c \
|
||||
xed-documents-panel.c \
|
||||
xed-encodings.c \
|
||||
xed-encodings-combo-box.c \
|
||||
|
|
|
@ -124,7 +124,7 @@ is_duplicated_file (GSList *files,
|
|||
/* File loading */
|
||||
static gint
|
||||
load_file_list (XedWindow *window,
|
||||
GSList *files,
|
||||
const GSList *files,
|
||||
const XedEncoding *encoding,
|
||||
gint line_pos,
|
||||
gboolean create)
|
||||
|
@ -134,7 +134,7 @@ load_file_list (XedWindow *window,
|
|||
gboolean jump_to = TRUE; /* Whether to jump to the new tab */
|
||||
GList *win_docs;
|
||||
GSList *files_to_load = NULL;
|
||||
GSList *l;
|
||||
const GSList *l;
|
||||
|
||||
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))
|
||||
{
|
||||
gchar *uri;
|
||||
|
||||
// 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);
|
||||
_xed_tab_load (tab, l->data, encoding, line_pos, create);
|
||||
|
||||
l = g_slist_next (l);
|
||||
jump_to = FALSE;
|
||||
|
@ -213,14 +208,9 @@ load_file_list (XedWindow *window,
|
|||
|
||||
while (l != NULL)
|
||||
{
|
||||
gchar *uri;
|
||||
|
||||
g_return_val_if_fail (l->data != NULL, 0);
|
||||
|
||||
// FIXME: pass the GFile to tab when api is there
|
||||
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);
|
||||
tab = xed_window_create_tab_from_location (window, l->data, encoding, line_pos, create, jump_to);
|
||||
|
||||
if (tab != NULL)
|
||||
{
|
||||
|
@ -264,114 +254,62 @@ load_file_list (XedWindow *window,
|
|||
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:
|
||||
* @uri:
|
||||
* @encoding: (allow-none):
|
||||
* @line_pos:
|
||||
*
|
||||
* Do nothing if uri does not exist
|
||||
* Do nothing if location does not exist
|
||||
*/
|
||||
void
|
||||
xed_commands_load_uri (XedWindow *window,
|
||||
const gchar *uri,
|
||||
xed_commands_load_location (XedWindow *window,
|
||||
GFile *location,
|
||||
const XedEncoding *encoding,
|
||||
gint line_pos)
|
||||
{
|
||||
GSList *uris = NULL;
|
||||
GSList *locations = NULL;
|
||||
gchar *uri;
|
||||
|
||||
g_return_if_fail (XED_IS_WINDOW (window));
|
||||
g_return_if_fail (uri != NULL);
|
||||
g_return_if_fail (xed_utils_is_valid_uri (uri));
|
||||
g_return_if_fail (G_IS_FILE (location));
|
||||
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);
|
||||
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:
|
||||
* @uris:
|
||||
* @encoding:
|
||||
* @line_pos:
|
||||
*
|
||||
* Ignore non-existing URIs
|
||||
* Ignore non-existing locations
|
||||
*
|
||||
* Returns:
|
||||
*/
|
||||
gint
|
||||
xed_commands_load_uris (XedWindow *window,
|
||||
const GSList *uris,
|
||||
xed_commands_load_locations (XedWindow *window,
|
||||
const GSList *locations,
|
||||
const XedEncoding *encoding,
|
||||
gint line_pos)
|
||||
{
|
||||
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);
|
||||
|
||||
return load_uri_list (window, uris, 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);
|
||||
return load_file_list (window, locations, encoding, line_pos, FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -426,7 +364,7 @@ open_dialog_response_cb (XedFileChooserDialog *dialog,
|
|||
/* Remember the folder we navigated to */
|
||||
_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_free (files);
|
||||
|
@ -616,7 +554,6 @@ save_dialog_response_cb (XedFileChooserDialog *dialog,
|
|||
{
|
||||
XedDocument *doc;
|
||||
gchar *parse_name;
|
||||
gchar *uri;
|
||||
|
||||
doc = xed_tab_get_document (tab);
|
||||
g_return_if_fail (XED_IS_DOCUMENT (doc));
|
||||
|
@ -634,10 +571,7 @@ save_dialog_response_cb (XedFileChooserDialog *dialog,
|
|||
* even if the saving fails... */
|
||||
_xed_window_set_default_location (window, file);
|
||||
|
||||
// FIXME: pass the GFile to tab when api is there
|
||||
uri = g_file_get_uri (file);
|
||||
_xed_tab_save_as (tab, uri, encoding, newline_type);
|
||||
g_free (uri);
|
||||
_xed_tab_save_as (tab, file, encoding, newline_type);
|
||||
}
|
||||
|
||||
g_object_unref (file);
|
||||
|
|
|
@ -7,10 +7,10 @@
|
|||
G_BEGIN_DECLS
|
||||
|
||||
/* 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 */
|
||||
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_all_documents (XedWindow *window);
|
||||
|
||||
|
|
|
@ -34,39 +34,91 @@
|
|||
#endif
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
#include <glib/gstdio.h>
|
||||
#include <gio/gio.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-metadata-manager.h"
|
||||
#include "xed-utils.h"
|
||||
#include "xed-marshal.h"
|
||||
#include "xed-enum-types.h"
|
||||
|
||||
/* Those are for the the xed_document_loader_new() factory */
|
||||
#include "xed-gio-document-loader.h"
|
||||
#ifndef ENABLE_GVFS_METADATA
|
||||
#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,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
static guint signals[LAST_SIGNAL] = { 0 };
|
||||
|
||||
/* Properties */
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_DOCUMENT,
|
||||
PROP_URI,
|
||||
PROP_LOCATION,
|
||||
PROP_ENCODING,
|
||||
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
|
||||
xed_document_loader_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
|
@ -78,19 +130,19 @@ xed_document_loader_set_property (GObject *object,
|
|||
switch (prop_id)
|
||||
{
|
||||
case PROP_DOCUMENT:
|
||||
g_return_if_fail (loader->document == NULL);
|
||||
loader->document = g_value_get_object (value);
|
||||
g_return_if_fail (loader->priv->document == NULL);
|
||||
loader->priv->document = g_value_get_object (value);
|
||||
break;
|
||||
case PROP_URI:
|
||||
g_return_if_fail (loader->uri == NULL);
|
||||
loader->uri = g_value_dup_string (value);
|
||||
case PROP_LOCATION:
|
||||
g_return_if_fail (loader->priv->location == NULL);
|
||||
loader->priv->location = g_value_dup_object (value);
|
||||
break;
|
||||
case PROP_ENCODING:
|
||||
g_return_if_fail (loader->encoding == NULL);
|
||||
loader->encoding = g_value_get_boxed (value);
|
||||
g_return_if_fail (loader->priv->encoding == NULL);
|
||||
loader->priv->encoding = g_value_get_boxed (value);
|
||||
break;
|
||||
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;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
|
@ -109,16 +161,16 @@ xed_document_loader_get_property (GObject *object,
|
|||
switch (prop_id)
|
||||
{
|
||||
case PROP_DOCUMENT:
|
||||
g_value_set_object (value, loader->document);
|
||||
g_value_set_object (value, loader->priv->document);
|
||||
break;
|
||||
case PROP_URI:
|
||||
g_value_set_string (value, loader->uri);
|
||||
case PROP_LOCATION:
|
||||
g_value_set_object (value, loader->priv->location);
|
||||
break;
|
||||
case PROP_ENCODING:
|
||||
g_value_set_boxed (value, xed_document_loader_get_encoding (loader));
|
||||
break;
|
||||
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;
|
||||
default:
|
||||
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
|
||||
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);
|
||||
loader->info = 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->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);
|
||||
|
@ -158,7 +236,6 @@ xed_document_loader_class_init (XedDocumentLoaderClass *klass)
|
|||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = xed_document_loader_finalize;
|
||||
object_class->dispose = xed_document_loader_dispose;
|
||||
object_class->get_property = xed_document_loader_get_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_object_class_install_property (object_class,
|
||||
PROP_URI,
|
||||
g_param_spec_string ("uri",
|
||||
"URI",
|
||||
"The URI this XedDocumentLoader loads the document from",
|
||||
"",
|
||||
PROP_LOCATION,
|
||||
g_param_spec_object ("location",
|
||||
"LOCATION",
|
||||
"The LOCATION this XedDocumentLoader loads the document from",
|
||||
G_TYPE_FILE,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY));
|
||||
|
||||
|
@ -192,7 +269,8 @@ xed_document_loader_class_init (XedDocumentLoaderClass *klass)
|
|||
G_PARAM_CONSTRUCT_ONLY |
|
||||
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",
|
||||
"Newline type",
|
||||
"The accepted types of line ending",
|
||||
|
@ -202,8 +280,7 @@ xed_document_loader_class_init (XedDocumentLoaderClass *klass)
|
|||
G_PARAM_STATIC_NAME |
|
||||
G_PARAM_STATIC_BLURB));
|
||||
|
||||
signals[LOADING] =
|
||||
g_signal_new ("loading",
|
||||
signals[LOADING] = g_signal_new ("loading",
|
||||
G_OBJECT_CLASS_TYPE (object_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (XedDocumentLoaderClass, loading),
|
||||
|
@ -213,13 +290,509 @@ xed_document_loader_class_init (XedDocumentLoaderClass *klass)
|
|||
2,
|
||||
G_TYPE_BOOLEAN,
|
||||
G_TYPE_POINTER);
|
||||
|
||||
g_type_class_add_private (object_class, sizeof (XedDocumentLoaderPrivate));
|
||||
}
|
||||
|
||||
static void
|
||||
xed_document_loader_init (XedDocumentLoader *loader)
|
||||
{
|
||||
loader->used = FALSE;
|
||||
loader->auto_detected_newline_type = XED_DOCUMENT_NEWLINE_TYPE_DEFAULT;
|
||||
loader->priv = XED_DOCUMENT_LOADER_GET_PRIVATE (loader);
|
||||
|
||||
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
|
||||
|
@ -240,54 +813,41 @@ xed_document_loader_loading (XedDocumentLoader *loader,
|
|||
if (completed)
|
||||
{
|
||||
if (error == NULL)
|
||||
{
|
||||
xed_debug_message (DEBUG_LOADER, "load completed");
|
||||
}
|
||||
else
|
||||
{
|
||||
xed_debug_message (DEBUG_LOADER, "load failed");
|
||||
}
|
||||
|
||||
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
|
||||
xed_document_loader_load (XedDocumentLoader *loader)
|
||||
{
|
||||
AsyncData *async;
|
||||
|
||||
xed_debug (DEBUG_LOADER);
|
||||
|
||||
g_return_if_fail (XED_IS_DOCUMENT_LOADER (loader));
|
||||
|
||||
/* the loader can be used just once, then it must be thrown away */
|
||||
g_return_if_fail (loader->used == FALSE);
|
||||
loader->used = TRUE;
|
||||
g_return_if_fail (loader->priv->used == FALSE);
|
||||
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
|
||||
|
@ -297,7 +857,21 @@ xed_document_loader_cancel (XedDocumentLoader *loader)
|
|||
|
||||
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 *
|
||||
|
@ -305,16 +879,16 @@ xed_document_loader_get_document (XedDocumentLoader *loader)
|
|||
{
|
||||
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 */
|
||||
const gchar *
|
||||
xed_document_loader_get_uri (XedDocumentLoader *loader)
|
||||
GFile *
|
||||
xed_document_loader_get_location (XedDocumentLoader *loader)
|
||||
{
|
||||
g_return_val_if_fail (XED_IS_DOCUMENT_LOADER (loader), NULL);
|
||||
|
||||
return loader->uri;
|
||||
return g_file_dup (loader->priv->location);
|
||||
}
|
||||
|
||||
goffset
|
||||
|
@ -322,7 +896,7 @@ xed_document_loader_get_bytes_read (XedDocumentLoader *loader)
|
|||
{
|
||||
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 *
|
||||
|
@ -330,22 +904,22 @@ xed_document_loader_get_encoding (XedDocumentLoader *loader)
|
|||
{
|
||||
g_return_val_if_fail (XED_IS_DOCUMENT_LOADER (loader), NULL);
|
||||
|
||||
if (loader->encoding != NULL)
|
||||
return loader->encoding;
|
||||
if (loader->priv->encoding != NULL)
|
||||
{
|
||||
return loader->priv->encoding;
|
||||
}
|
||||
|
||||
g_return_val_if_fail (loader->auto_detected_encoding != NULL,
|
||||
xed_encoding_get_current ());
|
||||
g_return_val_if_fail (loader->priv->auto_detected_encoding != NULL, xed_encoding_get_current ());
|
||||
|
||||
return loader->auto_detected_encoding;
|
||||
return loader->priv->auto_detected_encoding;
|
||||
}
|
||||
|
||||
XedDocumentNewlineType
|
||||
xed_document_loader_get_newline_type (XedDocumentLoader *loader)
|
||||
{
|
||||
g_return_val_if_fail (XED_IS_DOCUMENT_LOADER (loader),
|
||||
XED_DOCUMENT_NEWLINE_TYPE_LF);
|
||||
g_return_val_if_fail (XED_IS_DOCUMENT_LOADER (loader), XED_DOCUMENT_NEWLINE_TYPE_LF);
|
||||
|
||||
return loader->auto_detected_newline_type;
|
||||
return loader->priv->auto_detected_newline_type;
|
||||
}
|
||||
|
||||
GFileInfo *
|
||||
|
@ -353,5 +927,5 @@ xed_document_loader_get_info (XedDocumentLoader *loader)
|
|||
{
|
||||
g_return_val_if_fail (XED_IS_DOCUMENT_LOADER (loader), NULL);
|
||||
|
||||
return loader->info;
|
||||
return loader->priv->info;
|
||||
}
|
||||
|
|
|
@ -36,9 +36,6 @@
|
|||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/*
|
||||
* Type checking and casting macros
|
||||
*/
|
||||
#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_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_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 _XedDocumentLoaderPrivate XedDocumentLoaderPrivate;
|
||||
typedef struct _XedDocumentLoaderClass XedDocumentLoaderClass;
|
||||
|
||||
struct _XedDocumentLoader
|
||||
{
|
||||
GObject object;
|
||||
|
||||
XedDocument *document;
|
||||
gboolean used;
|
||||
|
||||
/* Info on the current file */
|
||||
GFileInfo *info;
|
||||
gchar *uri;
|
||||
const XedEncoding *encoding;
|
||||
const XedEncoding *auto_detected_encoding;
|
||||
XedDocumentNewlineType auto_detected_newline_type;
|
||||
XedDocumentLoaderPrivate *priv;
|
||||
};
|
||||
|
||||
/*
|
||||
* Class definition
|
||||
*/
|
||||
typedef struct _XedDocumentLoaderClass XedDocumentLoaderClass;
|
||||
|
||||
struct _XedDocumentLoaderClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
|
@ -82,21 +62,13 @@ struct _XedDocumentLoaderClass
|
|||
void (* loading) (XedDocumentLoader *loader,
|
||||
gboolean completed,
|
||||
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;
|
||||
|
||||
/* If enconding == NULL, the encoding will be autodetected */
|
||||
XedDocumentLoader *xed_document_loader_new (XedDocument *doc,
|
||||
const gchar *uri,
|
||||
GFile *location,
|
||||
const XedEncoding *encoding);
|
||||
|
||||
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 */
|
||||
#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);
|
||||
|
||||
|
|
|
@ -31,42 +31,87 @@
|
|||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
#include <glib.h>
|
||||
#include <gio/gio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "xed-document-saver.h"
|
||||
#include "xed-debug.h"
|
||||
#include "xed-document-input-stream.h"
|
||||
#include "xed-prefs-manager.h"
|
||||
#include "xed-marshal.h"
|
||||
#include "xed-utils.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,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
static guint signals[LAST_SIGNAL] = { 0 };
|
||||
|
||||
/* Properties */
|
||||
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_DOCUMENT,
|
||||
PROP_URI,
|
||||
PROP_LOCATION,
|
||||
PROP_ENCODING,
|
||||
PROP_NEWLINE_TYPE,
|
||||
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
|
||||
xed_document_saver_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
|
@ -78,22 +123,22 @@ xed_document_saver_set_property (GObject *object,
|
|||
switch (prop_id)
|
||||
{
|
||||
case PROP_DOCUMENT:
|
||||
g_return_if_fail (saver->document == NULL);
|
||||
saver->document = g_value_get_object (value);
|
||||
g_return_if_fail (saver->priv->document == NULL);
|
||||
saver->priv->document = g_value_get_object (value);
|
||||
break;
|
||||
case PROP_URI:
|
||||
g_return_if_fail (saver->uri == NULL);
|
||||
saver->uri = g_value_dup_string (value);
|
||||
case PROP_LOCATION:
|
||||
g_return_if_fail (saver->priv->location == NULL);
|
||||
saver->priv->location = g_value_dup_object (value);
|
||||
break;
|
||||
case PROP_ENCODING:
|
||||
g_return_if_fail (saver->encoding == NULL);
|
||||
saver->encoding = g_value_get_boxed (value);
|
||||
g_return_if_fail (saver->priv->encoding == NULL);
|
||||
saver->priv->encoding = g_value_get_boxed (value);
|
||||
break;
|
||||
case PROP_NEWLINE_TYPE:
|
||||
saver->newline_type = g_value_get_enum (value);
|
||||
saver->priv->newline_type = g_value_get_enum (value);
|
||||
break;
|
||||
case PROP_FLAGS:
|
||||
saver->flags = g_value_get_flags (value);
|
||||
saver->priv->flags = g_value_get_flags (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
|
@ -112,19 +157,19 @@ xed_document_saver_get_property (GObject *object,
|
|||
switch (prop_id)
|
||||
{
|
||||
case PROP_DOCUMENT:
|
||||
g_value_set_object (value, saver->document);
|
||||
g_value_set_object (value, saver->priv->document);
|
||||
break;
|
||||
case PROP_URI:
|
||||
g_value_set_string (value, saver->uri);
|
||||
case PROP_LOCATION:
|
||||
g_value_set_object (value, saver->priv->location);
|
||||
break;
|
||||
case PROP_ENCODING:
|
||||
g_value_set_boxed (value, saver->encoding);
|
||||
g_value_set_boxed (value, saver->priv->encoding);
|
||||
break;
|
||||
case PROP_NEWLINE_TYPE:
|
||||
g_value_set_enum (value, saver->newline_type);
|
||||
g_value_set_enum (value, saver->priv->newline_type);
|
||||
break;
|
||||
case PROP_FLAGS:
|
||||
g_value_set_flags (value, saver->flags);
|
||||
g_value_set_flags (value, saver->priv->flags);
|
||||
break;
|
||||
default:
|
||||
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
|
||||
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);
|
||||
saver->info = NULL;
|
||||
g_cancellable_cancel (priv->cancellable);
|
||||
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);
|
||||
}
|
||||
|
||||
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
|
||||
xed_document_saver_class_init (XedDocumentSaverClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = xed_document_saver_finalize;
|
||||
object_class->dispose = xed_document_saver_dispose;
|
||||
object_class->set_property = xed_document_saver_set_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_object_class_install_property (object_class,
|
||||
PROP_URI,
|
||||
g_param_spec_string ("uri",
|
||||
"URI",
|
||||
"The URI this XedDocumentSaver saves the document to",
|
||||
"",
|
||||
PROP_LOCATION,
|
||||
g_param_spec_object ("location",
|
||||
"LOCATION",
|
||||
"The LOCATION this XedDocumentSaver saves the document to",
|
||||
G_TYPE_FILE,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
|
@ -189,7 +285,7 @@ xed_document_saver_class_init (XedDocumentSaverClass *klass)
|
|||
g_object_class_install_property (object_class,
|
||||
PROP_ENCODING,
|
||||
g_param_spec_boxed ("encoding",
|
||||
"URI",
|
||||
"ENCODING",
|
||||
"The encoding of the saved file",
|
||||
XED_TYPE_ENCODING,
|
||||
G_PARAM_READWRITE |
|
||||
|
@ -229,40 +325,630 @@ xed_document_saver_class_init (XedDocumentSaverClass *klass)
|
|||
2,
|
||||
G_TYPE_BOOLEAN,
|
||||
G_TYPE_POINTER);
|
||||
|
||||
g_type_class_add_private (object_class, sizeof (XedDocumentSaverPrivate));
|
||||
}
|
||||
|
||||
static void
|
||||
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 *
|
||||
xed_document_saver_new (XedDocument *doc,
|
||||
const gchar *uri,
|
||||
GFile *location,
|
||||
const XedEncoding *encoding,
|
||||
XedDocumentNewlineType newline_type,
|
||||
XedDocumentSaveFlags flags)
|
||||
{
|
||||
XedDocumentSaver *saver;
|
||||
GType saver_type;
|
||||
|
||||
g_return_val_if_fail (XED_IS_DOCUMENT (doc), NULL);
|
||||
|
||||
saver_type = XED_TYPE_GIO_DOCUMENT_SAVER;
|
||||
|
||||
if (encoding == NULL)
|
||||
{
|
||||
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,
|
||||
"uri", uri,
|
||||
"location", location,
|
||||
"encoding", encoding,
|
||||
"newline_type", newline_type,
|
||||
"flags", flags,
|
||||
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
|
||||
|
@ -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 *
|
||||
xed_document_saver_get_document (XedDocumentSaver *saver)
|
||||
{
|
||||
g_return_val_if_fail (XED_IS_DOCUMENT_SAVER (saver), NULL);
|
||||
|
||||
return saver->document;
|
||||
return saver->priv->document;
|
||||
}
|
||||
|
||||
const gchar *
|
||||
xed_document_saver_get_uri (XedDocumentSaver *saver)
|
||||
GFile *
|
||||
xed_document_saver_get_location (XedDocumentSaver *saver)
|
||||
{
|
||||
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 */
|
||||
|
@ -339,7 +999,7 @@ xed_document_saver_get_file_size (XedDocumentSaver *saver)
|
|||
{
|
||||
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
|
||||
|
@ -347,7 +1007,7 @@ xed_document_saver_get_bytes_written (XedDocumentSaver *saver)
|
|||
{
|
||||
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 *
|
||||
|
@ -355,5 +1015,5 @@ xed_document_saver_get_info (XedDocumentSaver *saver)
|
|||
{
|
||||
g_return_val_if_fail (XED_IS_DOCUMENT_SAVER (saver), NULL);
|
||||
|
||||
return saver->info;
|
||||
return saver->priv->info;
|
||||
}
|
||||
|
|
|
@ -25,8 +25,6 @@
|
|||
* Modified by the xed Team, 2005. 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_DOCUMENT_SAVER_H__
|
||||
|
@ -36,9 +34,6 @@
|
|||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/*
|
||||
* Type checking and casting macros
|
||||
*/
|
||||
#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_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_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 _XedDocumentSaverPrivate XedDocumentSaverPrivate;
|
||||
typedef struct _XedDocumentSaverClass XedDocumentSaverClass;
|
||||
|
||||
struct _XedDocumentSaver
|
||||
{
|
||||
GObject object;
|
||||
|
||||
/*< private >*/
|
||||
GFileInfo *info;
|
||||
XedDocument *document;
|
||||
gboolean used;
|
||||
|
||||
gchar *uri;
|
||||
const XedEncoding *encoding;
|
||||
XedDocumentNewlineType newline_type;
|
||||
|
||||
XedDocumentSaveFlags flags;
|
||||
|
||||
gboolean keep_backup;
|
||||
XedDocumentSaverPrivate *priv;
|
||||
};
|
||||
|
||||
/*
|
||||
* Class definition
|
||||
*/
|
||||
typedef struct _XedDocumentSaverClass XedDocumentSaverClass;
|
||||
|
||||
struct _XedDocumentSaverClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
|
@ -82,22 +61,13 @@ struct _XedDocumentSaverClass
|
|||
void (* saving) (XedDocumentSaver *saver,
|
||||
gboolean completed,
|
||||
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;
|
||||
|
||||
/* If enconding == NULL, the encoding will be autodetected */
|
||||
XedDocumentSaver *xed_document_saver_new (XedDocument *doc,
|
||||
const gchar *uri,
|
||||
GFile *location,
|
||||
const XedEncoding *encoding,
|
||||
XedDocumentNewlineType newline_type,
|
||||
XedDocumentSaveFlags flags);
|
||||
|
@ -114,7 +84,7 @@ void xed_document_saver_cancel (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 */
|
||||
const gchar *xed_document_saver_get_backup_uri (XedDocumentSaver *saver);
|
||||
|
|
|
@ -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))
|
||||
|
||||
static void xed_document_load_real (XedDocument *doc,
|
||||
const gchar *uri,
|
||||
GFile *location,
|
||||
const XedEncoding *encoding,
|
||||
gint line_pos,
|
||||
gboolean create);
|
||||
static void xed_document_save_real (XedDocument *doc,
|
||||
const gchar *uri,
|
||||
GFile *location,
|
||||
const XedEncoding *encoding,
|
||||
XedDocumentSaveFlags flags);
|
||||
static void to_search_region_range (XedDocument *doc,
|
||||
|
@ -102,7 +102,7 @@ static void delete_range_cb (XedDocument *doc,
|
|||
|
||||
struct _XedDocumentPrivate
|
||||
{
|
||||
gchar *uri;
|
||||
GFile *location;
|
||||
gint untitled_number;
|
||||
gchar *short_name;
|
||||
|
||||
|
@ -150,7 +150,7 @@ enum
|
|||
{
|
||||
PROP_0,
|
||||
|
||||
PROP_URI,
|
||||
PROP_LOCATION,
|
||||
PROP_SHORTNAME,
|
||||
PROP_CONTENT_TYPE,
|
||||
PROP_MIME_TYPE,
|
||||
|
@ -237,7 +237,7 @@ xed_document_dispose (GObject *object)
|
|||
* because the language is gone by the time finalize runs.
|
||||
* beside if some plugin prevents proper finalization by
|
||||
* 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;
|
||||
gchar *position;
|
||||
|
@ -290,6 +290,12 @@ xed_document_dispose (GObject *object)
|
|||
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;
|
||||
|
||||
G_OBJECT_CLASS (xed_document_parent_class)->dispose (object);
|
||||
|
@ -304,11 +310,9 @@ xed_document_finalize (GObject *object)
|
|||
|
||||
if (doc->priv->untitled_number > 0)
|
||||
{
|
||||
g_return_if_fail (doc->priv->uri == NULL);
|
||||
release_untitled_number (doc->priv->untitled_number);
|
||||
}
|
||||
|
||||
g_free (doc->priv->uri);
|
||||
g_free (doc->priv->content_type);
|
||||
g_free (doc->priv->search_text);
|
||||
|
||||
|
@ -331,8 +335,8 @@ xed_document_get_property (GObject *object,
|
|||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_URI:
|
||||
g_value_set_string (value, doc->priv->uri);
|
||||
case PROP_LOCATION:
|
||||
g_value_set_object (value, doc->priv->location);
|
||||
break;
|
||||
case PROP_SHORTNAME:
|
||||
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->save = xed_document_save_real;
|
||||
|
||||
g_object_class_install_property (object_class, PROP_URI,
|
||||
g_param_spec_string ("uri",
|
||||
"URI",
|
||||
"The document's URI",
|
||||
NULL,
|
||||
g_object_class_install_property (object_class, PROP_LOCATION,
|
||||
g_param_spec_object ("location",
|
||||
"LOCATION",
|
||||
"The document's location",
|
||||
G_TYPE_FILE,
|
||||
G_PARAM_READABLE |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
|
||||
|
@ -543,7 +547,7 @@ xed_document_class_init (XedDocumentClass *klass)
|
|||
/**
|
||||
* XedDocument::load:
|
||||
* @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.
|
||||
* @line_pos: the line to show.
|
||||
* @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_STRUCT_OFFSET (XedDocumentClass, load),
|
||||
NULL, NULL,
|
||||
xed_marshal_VOID__STRING_BOXED_INT_BOOLEAN,
|
||||
xed_marshal_VOID__OBJECT_BOXED_INT_BOOLEAN,
|
||||
G_TYPE_NONE,
|
||||
4,
|
||||
G_TYPE_STRING,
|
||||
G_TYPE_FILE,
|
||||
/* we rely on the fact that the XedEncoding pointer stays
|
||||
* the same forever */
|
||||
XED_TYPE_ENCODING | G_SIGNAL_TYPE_STATIC_SCOPE,
|
||||
|
@ -593,7 +597,7 @@ xed_document_class_init (XedDocumentClass *klass)
|
|||
/**
|
||||
* XedDocument::save:
|
||||
* @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.
|
||||
* @flags: the #XedDocumentSaveFlags for the save operation.
|
||||
*
|
||||
|
@ -605,10 +609,10 @@ xed_document_class_init (XedDocumentClass *klass)
|
|||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (XedDocumentClass, save),
|
||||
NULL, NULL,
|
||||
xed_marshal_VOID__STRING_BOXED_FLAGS,
|
||||
xed_marshal_VOID__OBJECT_BOXED_FLAGS,
|
||||
G_TYPE_NONE,
|
||||
3,
|
||||
G_TYPE_STRING,
|
||||
G_TYPE_FILE,
|
||||
/* we rely on the fact that the XedEncoding pointer stays
|
||||
* the same forever */
|
||||
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);
|
||||
}
|
||||
|
||||
if (set_by_user && (doc->priv->uri != NULL))
|
||||
if (set_by_user)
|
||||
{
|
||||
xed_document_set_metadata (doc, XED_METADATA_ATTRIBUTE_LANGUAGE,
|
||||
(lang == NULL) ? "_NORMAL_" : gtk_source_language_get_id (lang),
|
||||
|
@ -747,7 +751,7 @@ get_default_style_scheme (void)
|
|||
}
|
||||
|
||||
static void
|
||||
on_uri_changed (XedDocument *doc,
|
||||
on_location_changed (XedDocument *doc,
|
||||
GParamSpec *pspec,
|
||||
gpointer useless)
|
||||
{
|
||||
|
@ -756,9 +760,9 @@ on_uri_changed (XedDocument *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
|
||||
* right after the uri was set.
|
||||
* right after the location was set.
|
||||
*/
|
||||
if (location != NULL)
|
||||
{
|
||||
|
@ -814,15 +818,15 @@ guess_language (XedDocument *doc,
|
|||
}
|
||||
else
|
||||
{
|
||||
GFile *file;
|
||||
GFile *location;
|
||||
gchar *basename = NULL;
|
||||
|
||||
file = xed_document_get_location (doc);
|
||||
location = xed_document_get_location (doc);
|
||||
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)
|
||||
{
|
||||
|
@ -833,9 +837,9 @@ guess_language (XedDocument *doc,
|
|||
|
||||
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->uri = NULL;
|
||||
doc->priv->location = NULL;
|
||||
doc->priv->untitled_number = get_untitled_number ();
|
||||
|
||||
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, "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::uri", G_CALLBACK (on_uri_changed), NULL);
|
||||
g_signal_connect (doc, "notify::location", G_CALLBACK (on_location_changed), NULL);
|
||||
}
|
||||
|
||||
XedDocument *
|
||||
|
@ -959,20 +963,20 @@ set_content_type (XedDocument *doc,
|
|||
|
||||
if (content_type == NULL)
|
||||
{
|
||||
GFile *file;
|
||||
GFile *location;
|
||||
gchar *guessed_type = NULL;
|
||||
|
||||
/* If content type is null, we guess from the filename */
|
||||
file = xed_document_get_location (doc);
|
||||
if (file != NULL)
|
||||
location = xed_document_get_location (doc);
|
||||
if (location != NULL)
|
||||
{
|
||||
gchar *basename;
|
||||
|
||||
basename = g_file_get_basename (file);
|
||||
basename = g_file_get_basename (location);
|
||||
guessed_type = g_content_type_guess (basename, NULL, 0, NULL);
|
||||
|
||||
g_free (basename);
|
||||
g_object_unref (file);
|
||||
g_object_unref (location);
|
||||
}
|
||||
|
||||
set_content_type_no_guess (doc, guessed_type);
|
||||
|
@ -1000,22 +1004,26 @@ xed_document_set_content_type (XedDocument *doc,
|
|||
}
|
||||
|
||||
static void
|
||||
set_uri (XedDocument *doc,
|
||||
const gchar *uri)
|
||||
set_location (XedDocument *doc,
|
||||
GFile *location)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
g_free (doc->priv->uri);
|
||||
doc->priv->uri = g_strdup (uri);
|
||||
if (doc->priv->location != NULL)
|
||||
{
|
||||
g_object_unref (doc->priv->location);
|
||||
}
|
||||
|
||||
doc->priv->location = g_file_dup (location);
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -1043,25 +1051,17 @@ xed_document_get_location (XedDocument *doc)
|
|||
{
|
||||
g_return_val_if_fail (XED_IS_DOCUMENT (doc), NULL);
|
||||
|
||||
return doc->priv->uri == NULL ? NULL : g_file_new_for_uri (doc->priv->uri);
|
||||
}
|
||||
|
||||
gchar *
|
||||
xed_document_get_uri (XedDocument *doc)
|
||||
{
|
||||
g_return_val_if_fail (XED_IS_DOCUMENT (doc), NULL);
|
||||
|
||||
return g_strdup (doc->priv->uri);
|
||||
return doc->priv->location == NULL ? NULL : g_file_dup (doc->priv->location);
|
||||
}
|
||||
|
||||
void
|
||||
xed_document_set_uri (XedDocument *doc,
|
||||
const gchar *uri)
|
||||
xed_document_set_location (XedDocument *doc,
|
||||
GFile *location)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -1076,13 +1076,13 @@ xed_document_get_uri_for_display (XedDocument *doc)
|
|||
{
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
else if (doc->priv->uri == NULL)
|
||||
else if (doc->priv->location == NULL)
|
||||
{
|
||||
return g_strdup_printf (_("Unsaved Document %d"), doc->priv->untitled_number);
|
||||
}
|
||||
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
|
||||
_xed_document_check_externally_modified (XedDocument *doc)
|
||||
{
|
||||
GFile *gfile;
|
||||
GFileInfo *info;
|
||||
|
||||
g_return_val_if_fail (XED_IS_DOCUMENT (doc), FALSE);
|
||||
|
||||
if (doc->priv->uri == NULL)
|
||||
if (doc->priv->location == NULL)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gfile = g_file_new_for_uri (doc->priv->uri);
|
||||
info = g_file_query_info (gfile,
|
||||
info = g_file_query_info (doc->priv->location,
|
||||
G_FILE_ATTRIBUTE_TIME_MODIFIED "," \
|
||||
G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE,
|
||||
G_FILE_QUERY_INFO_NONE,
|
||||
NULL, NULL);
|
||||
g_object_unref (gfile);
|
||||
|
||||
if (info != NULL)
|
||||
{
|
||||
|
@ -1353,7 +1350,7 @@ document_loader_loaded (XedDocumentLoader *loader,
|
|||
/* special case creating a named new doc */
|
||||
else if (doc->priv->create &&
|
||||
(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);
|
||||
|
||||
|
@ -1398,17 +1395,21 @@ document_loader_loading (XedDocumentLoader *loader,
|
|||
|
||||
static void
|
||||
xed_document_load_real (XedDocument *doc,
|
||||
const gchar *uri,
|
||||
GFile *location,
|
||||
const XedEncoding *encoding,
|
||||
gint line_pos,
|
||||
gboolean create)
|
||||
{
|
||||
gchar *uri;
|
||||
|
||||
g_return_if_fail (doc->priv->loader == NULL);
|
||||
|
||||
uri = g_file_get_uri (location);
|
||||
xed_debug_message (DEBUG_DOCUMENT, "load_real: uri = %s", uri);
|
||||
g_free (uri);
|
||||
|
||||
/* 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);
|
||||
|
||||
|
@ -1416,7 +1417,7 @@ xed_document_load_real (XedDocument *doc,
|
|||
doc->priv->requested_encoding = encoding;
|
||||
doc->priv->requested_line_pos = line_pos;
|
||||
|
||||
set_uri (doc, uri);
|
||||
set_location (doc, location);
|
||||
set_content_type (doc, NULL);
|
||||
|
||||
xed_document_loader_load (doc->priv->loader);
|
||||
|
@ -1425,7 +1426,7 @@ xed_document_load_real (XedDocument *doc,
|
|||
/**
|
||||
* xed_document_load:
|
||||
* @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.
|
||||
* @line_pos: the line to show.
|
||||
* @create: whether the document should be created if it doesn't exist.
|
||||
|
@ -1434,16 +1435,16 @@ xed_document_load_real (XedDocument *doc,
|
|||
*/
|
||||
void
|
||||
xed_document_load (XedDocument *doc,
|
||||
const gchar *uri,
|
||||
GFile *location,
|
||||
const XedEncoding *encoding,
|
||||
gint line_pos,
|
||||
gboolean create)
|
||||
{
|
||||
g_return_if_fail (XED_IS_DOCUMENT (doc));
|
||||
g_return_if_fail (uri != NULL);
|
||||
g_return_if_fail (xed_utils_is_valid_uri (uri));
|
||||
g_return_if_fail (location != NULL);
|
||||
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 */
|
||||
if (error == NULL)
|
||||
{
|
||||
const gchar *uri;
|
||||
GFile *location;
|
||||
const gchar *content_type = NULL;
|
||||
GTimeVal mtime = {0, 0};
|
||||
GFileInfo *info;
|
||||
|
||||
uri = xed_document_saver_get_uri (saver);
|
||||
set_uri (doc, uri);
|
||||
location = xed_document_saver_get_location (saver);
|
||||
set_location (doc, location);
|
||||
g_object_unref (location);
|
||||
|
||||
info = xed_document_saver_get_info (saver);
|
||||
|
||||
|
@ -1533,14 +1535,14 @@ document_saver_saving (XedDocumentSaver *saver,
|
|||
|
||||
static void
|
||||
xed_document_save_real (XedDocument *doc,
|
||||
const gchar *uri,
|
||||
GFile *location,
|
||||
const XedEncoding *encoding,
|
||||
XedDocumentSaveFlags flags)
|
||||
{
|
||||
g_return_if_fail (doc->priv->saver == NULL);
|
||||
|
||||
/* 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);
|
||||
|
||||
|
@ -1562,15 +1564,15 @@ xed_document_save (XedDocument *doc,
|
|||
XedDocumentSaveFlags flags)
|
||||
{
|
||||
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:
|
||||
* @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.
|
||||
* @flags: optionnal #XedDocumentSaveFlags.
|
||||
*
|
||||
|
@ -1579,32 +1581,17 @@ xed_document_save (XedDocument *doc,
|
|||
*/
|
||||
void
|
||||
xed_document_save_as (XedDocument *doc,
|
||||
const gchar *uri,
|
||||
GFile *location,
|
||||
const XedEncoding *encoding,
|
||||
XedDocumentSaveFlags flags)
|
||||
{
|
||||
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);
|
||||
|
||||
/* 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. */
|
||||
g_signal_emit (doc, document_signals[SAVE], 0, uri, 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;
|
||||
g_signal_emit (doc, document_signals[SAVE], 0, location, encoding, flags | XED_DOCUMENT_SAVE_IGNORE_MTIME);
|
||||
}
|
||||
|
||||
gboolean
|
||||
|
@ -1612,7 +1599,7 @@ xed_document_is_untouched (XedDocument *doc)
|
|||
{
|
||||
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
|
||||
|
@ -1620,7 +1607,7 @@ xed_document_is_untitled (XedDocument *doc)
|
|||
{
|
||||
g_return_val_if_fail (XED_IS_DOCUMENT (doc), TRUE);
|
||||
|
||||
return (doc->priv->uri == NULL);
|
||||
return (doc->priv->location == NULL);
|
||||
}
|
||||
|
||||
gboolean
|
||||
|
@ -1628,12 +1615,12 @@ xed_document_is_local (XedDocument *doc)
|
|||
{
|
||||
g_return_val_if_fail (XED_IS_DOCUMENT (doc), FALSE);
|
||||
|
||||
if (doc->priv->uri == NULL)
|
||||
if (doc->priv->location == NULL)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return xed_utils_uri_has_file_scheme (doc->priv->uri);
|
||||
return xed_utils_location_has_file_scheme (doc->priv->location);
|
||||
}
|
||||
|
||||
gboolean
|
||||
|
@ -1641,7 +1628,8 @@ xed_document_get_deleted (XedDocument *doc)
|
|||
{
|
||||
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,
|
||||
const gchar *key)
|
||||
{
|
||||
gchar *value = NULL;
|
||||
gchar *uri;
|
||||
|
||||
g_return_val_if_fail (XED_IS_DOCUMENT (doc), NULL);
|
||||
g_return_val_if_fail (key != NULL, NULL);
|
||||
|
||||
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;
|
||||
|
@ -2629,8 +2617,11 @@ xed_document_set_metadata (XedDocument *doc,
|
|||
{
|
||||
value = va_arg (var_args, const gchar *);
|
||||
|
||||
if (doc->priv->location != NULL)
|
||||
{
|
||||
xed_metadata_manager_set (doc->priv->uri, key, value);
|
||||
}
|
||||
}
|
||||
|
||||
va_end (var_args);
|
||||
}
|
||||
|
|
|
@ -117,7 +117,7 @@ struct _XedDocumentClass
|
|||
|
||||
/* Document load */
|
||||
void (* load) (XedDocument *document,
|
||||
const gchar *uri,
|
||||
GFile *location,
|
||||
const XedEncoding *encoding,
|
||||
gint line_pos,
|
||||
gboolean create);
|
||||
|
@ -131,7 +131,7 @@ struct _XedDocumentClass
|
|||
|
||||
/* Document save */
|
||||
void (* save) (XedDocument *document,
|
||||
const gchar *uri,
|
||||
GFile *location,
|
||||
const XedEncoding *encoding,
|
||||
XedDocumentSaveFlags flags);
|
||||
|
||||
|
@ -169,9 +169,8 @@ XedDocument *xed_document_new (void);
|
|||
|
||||
GFile *xed_document_get_location (XedDocument *doc);
|
||||
|
||||
gchar *xed_document_get_uri (XedDocument *doc);
|
||||
void xed_document_set_uri (XedDocument *doc,
|
||||
const gchar *uri);
|
||||
void xed_document_set_location (XedDocument *doc,
|
||||
GFile *location);
|
||||
|
||||
gchar *xed_document_get_uri_for_display
|
||||
(XedDocument *doc);
|
||||
|
@ -194,23 +193,18 @@ gchar *xed_document_get_mime_type (XedDocument *doc);
|
|||
gboolean xed_document_get_readonly (XedDocument *doc);
|
||||
|
||||
void xed_document_load (XedDocument *doc,
|
||||
const gchar *uri,
|
||||
GFile *location,
|
||||
const XedEncoding *encoding,
|
||||
gint line_pos,
|
||||
gboolean create);
|
||||
|
||||
gboolean xed_document_insert_file (XedDocument *doc,
|
||||
GtkTextIter *iter,
|
||||
const gchar *uri,
|
||||
const XedEncoding *encoding);
|
||||
|
||||
gboolean xed_document_load_cancel (XedDocument *doc);
|
||||
|
||||
void xed_document_save (XedDocument *doc,
|
||||
XedDocumentSaveFlags flags);
|
||||
|
||||
void xed_document_save_as (XedDocument *doc,
|
||||
const gchar *uri,
|
||||
GFile *location,
|
||||
const XedEncoding *encoding,
|
||||
XedDocumentSaveFlags flags);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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__ */
|
|
@ -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;
|
||||
}
|
|
@ -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__ */
|
|
@ -180,7 +180,7 @@ static gboolean
|
|||
parse_gio_error (gint code,
|
||||
gchar **error_message,
|
||||
gchar **message_details,
|
||||
const gchar *uri,
|
||||
GFile *location,
|
||||
const gchar *uri_for_display)
|
||||
{
|
||||
gboolean ret = TRUE;
|
||||
|
@ -198,7 +198,7 @@ parse_gio_error (gint code,
|
|||
gchar *scheme_string;
|
||||
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))
|
||||
{
|
||||
|
@ -240,8 +240,11 @@ parse_gio_error (gint code,
|
|||
*/
|
||||
{
|
||||
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)
|
||||
{
|
||||
|
@ -264,6 +267,8 @@ parse_gio_error (gint code,
|
|||
}
|
||||
}
|
||||
|
||||
g_free (uri);
|
||||
|
||||
if (!*message_details)
|
||||
{
|
||||
/* use the same string as INVALID_HOST */
|
||||
|
@ -291,7 +296,7 @@ static gboolean
|
|||
parse_xed_error (gint code,
|
||||
gchar **error_message,
|
||||
gchar **message_details,
|
||||
const gchar *uri,
|
||||
GFile *location,
|
||||
const gchar *uri_for_display)
|
||||
{
|
||||
gboolean ret = TRUE;
|
||||
|
@ -313,18 +318,18 @@ static void
|
|||
parse_error (const GError *error,
|
||||
gchar **error_message,
|
||||
gchar **message_details,
|
||||
const gchar *uri,
|
||||
GFile *location,
|
||||
const gchar *uri_for_display)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
|
@ -335,7 +340,7 @@ parse_error (const GError *error,
|
|||
}
|
||||
|
||||
GtkWidget *
|
||||
xed_unrecoverable_reverting_error_message_area_new (const gchar *uri,
|
||||
xed_unrecoverable_reverting_error_message_area_new (GFile *location,
|
||||
const GError *error)
|
||||
{
|
||||
gchar *error_message = NULL;
|
||||
|
@ -345,11 +350,11 @@ xed_unrecoverable_reverting_error_message_area_new (const gchar *uri,
|
|||
gchar *temp_uri_for_display;
|
||||
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->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
|
||||
* 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
|
||||
{
|
||||
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)
|
||||
|
@ -491,7 +496,7 @@ create_conversion_error_message_area (const gchar *primary_text,
|
|||
}
|
||||
|
||||
GtkWidget *
|
||||
xed_io_loading_error_message_area_new (const gchar *uri,
|
||||
xed_io_loading_error_message_area_new (GFile *location,
|
||||
const XedEncoding *encoding,
|
||||
const GError *error)
|
||||
{
|
||||
|
@ -505,13 +510,13 @@ xed_io_loading_error_message_area_new (const gchar *uri,
|
|||
gboolean edit_anyway = 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->domain == G_CONVERT_ERROR) ||
|
||||
(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
|
||||
* 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
|
||||
{
|
||||
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)
|
||||
|
@ -600,7 +605,7 @@ xed_io_loading_error_message_area_new (const gchar *uri,
|
|||
}
|
||||
|
||||
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 GError *error)
|
||||
{
|
||||
|
@ -612,13 +617,13 @@ xed_conversion_error_while_saving_message_area_new (const gchar *uri,
|
|||
gchar *temp_uri_for_display;
|
||||
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->domain == G_CONVERT_ERROR ||
|
||||
error->domain == G_IO_ERROR, 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
|
||||
* 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 *
|
||||
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 *hbox_content;
|
||||
|
@ -679,7 +684,9 @@ xed_file_already_open_warning_message_area_new (const gchar *uri)
|
|||
gchar *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
|
||||
* 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 *
|
||||
xed_externally_modified_saving_error_message_area_new (const gchar *uri,
|
||||
xed_externally_modified_saving_error_message_area_new (GFile *location,
|
||||
const GError *error)
|
||||
{
|
||||
GtkWidget *message_area;
|
||||
|
@ -764,12 +771,12 @@ xed_externally_modified_saving_error_message_area_new (const gchar *uri,
|
|||
gchar *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->domain == XED_DOCUMENT_ERROR, 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
|
||||
* 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 *
|
||||
xed_no_backup_saving_error_message_area_new (const gchar *uri,
|
||||
xed_no_backup_saving_error_message_area_new (GFile *location,
|
||||
const GError *error)
|
||||
{
|
||||
GtkWidget *message_area;
|
||||
|
@ -850,14 +857,14 @@ xed_no_backup_saving_error_message_area_new (const gchar *uri,
|
|||
gchar *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->domain == XED_DOCUMENT_ERROR &&
|
||||
error->code == XED_DOCUMENT_ERROR_CANT_CREATE_BACKUP) ||
|
||||
(error->domain == G_IO_ERROR &&
|
||||
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
|
||||
* 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 *
|
||||
xed_unrecoverable_saving_error_message_area_new (const gchar *uri,
|
||||
xed_unrecoverable_saving_error_message_area_new (GFile *location,
|
||||
const GError *error)
|
||||
{
|
||||
gchar *error_message = NULL;
|
||||
|
@ -942,11 +949,11 @@ xed_unrecoverable_saving_error_message_area_new (const gchar *uri,
|
|||
gchar *temp_uri_for_display;
|
||||
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->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
|
||||
* 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))
|
||||
{
|
||||
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))
|
||||
{
|
||||
|
@ -1025,7 +1032,7 @@ xed_unrecoverable_saving_error_message_area_new (const gchar *uri,
|
|||
}
|
||||
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)
|
||||
|
@ -1043,7 +1050,7 @@ xed_unrecoverable_saving_error_message_area_new (const gchar *uri,
|
|||
}
|
||||
|
||||
GtkWidget *
|
||||
xed_externally_modified_message_area_new (const gchar *uri,
|
||||
xed_externally_modified_message_area_new (GFile *location,
|
||||
gboolean document_modified)
|
||||
{
|
||||
gchar *full_formatted_uri;
|
||||
|
@ -1053,9 +1060,9 @@ xed_externally_modified_message_area_new (const gchar *uri,
|
|||
const gchar *secondary_text;
|
||||
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
|
||||
* though the dialog uses wrapped text, if the URI doesn't contain
|
||||
|
|
|
@ -35,32 +35,32 @@
|
|||
|
||||
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 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);
|
||||
|
||||
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 GError *error);
|
||||
|
||||
const XedEncoding
|
||||
*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);
|
||||
|
||||
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);
|
||||
|
||||
GtkWidget *xed_unrecoverable_saving_error_message_area_new (const gchar *uri,
|
||||
GtkWidget *xed_unrecoverable_saving_error_message_area_new (GFile *location,
|
||||
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);
|
||||
|
||||
G_END_DECLS
|
||||
|
|
|
@ -5,8 +5,8 @@ VOID:BOOLEAN,POINTER
|
|||
VOID:BOXED,BOXED
|
||||
VOID:OBJECT
|
||||
VOID:POINTER
|
||||
VOID:STRING,BOXED,FLAGS
|
||||
VOID:STRING,BOXED,INT,BOOLEAN
|
||||
VOID:OBJECT,BOXED,FLAGS
|
||||
VOID:OBJECT,BOXED,INT,BOOLEAN
|
||||
VOID:UINT,POINTER
|
||||
VOID:UINT64,UINT64
|
||||
VOID:VOID
|
||||
|
|
|
@ -301,15 +301,18 @@ load_values (void)
|
|||
}
|
||||
|
||||
gchar *
|
||||
xed_metadata_manager_get (const gchar *uri,
|
||||
xed_metadata_manager_get (GFile *location,
|
||||
const gchar *key)
|
||||
{
|
||||
Item *item;
|
||||
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);
|
||||
|
||||
uri = g_file_get_uri (location);
|
||||
|
||||
xed_debug_message (DEBUG_METADATA, "URI: %s --- key: %s", uri, key );
|
||||
|
||||
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,
|
||||
uri);
|
||||
|
||||
g_free (uri);
|
||||
|
||||
if (item == NULL)
|
||||
return NULL;
|
||||
|
||||
|
@ -344,15 +349,18 @@ xed_metadata_manager_get (const gchar *uri,
|
|||
}
|
||||
|
||||
void
|
||||
xed_metadata_manager_set (const gchar *uri,
|
||||
xed_metadata_manager_set (GFile *location,
|
||||
const gchar *key,
|
||||
const gchar *value)
|
||||
{
|
||||
Item *item;
|
||||
gchar *uri;
|
||||
|
||||
g_return_if_fail (uri != NULL);
|
||||
g_return_if_fail (G_IS_FILE (location));
|
||||
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_metadata_manager_init ();
|
||||
|
@ -394,6 +402,8 @@ xed_metadata_manager_set (const gchar *uri,
|
|||
|
||||
item->atime = time (NULL);
|
||||
|
||||
g_free (uri);
|
||||
|
||||
xed_metadata_manager_arm_timeout ();
|
||||
}
|
||||
|
||||
|
|
|
@ -39,9 +39,9 @@ G_BEGIN_DECLS
|
|||
void xed_metadata_manager_shutdown (void);
|
||||
|
||||
|
||||
gchar *xed_metadata_manager_get (const gchar *uri,
|
||||
gchar *xed_metadata_manager_get (GFile *location,
|
||||
const gchar *key);
|
||||
void xed_metadata_manager_set (const gchar *uri,
|
||||
void xed_metadata_manager_set (GFile *location,
|
||||
const gchar *key,
|
||||
const gchar *value);
|
||||
|
||||
|
|
|
@ -75,7 +75,7 @@ save_window_session (GKeyFile *state_file,
|
|||
GList *docs, *l;
|
||||
GPtrArray *doc_array;
|
||||
XedDocument *active_document;
|
||||
gchar *uri;
|
||||
gchar *uri = NULL;
|
||||
|
||||
xed_debug (DEBUG_SESSION);
|
||||
|
||||
|
@ -96,9 +96,17 @@ save_window_session (GKeyFile *state_file,
|
|||
active_document = xed_window_get_active_document (window);
|
||||
if (active_document)
|
||||
{
|
||||
uri = xed_document_get_uri (active_document);
|
||||
g_key_file_set_string (state_file, group_name,
|
||||
"active-document", uri);
|
||||
GFile *location;
|
||||
|
||||
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);
|
||||
|
@ -106,24 +114,30 @@ save_window_session (GKeyFile *state_file,
|
|||
doc_array = g_ptr_array_new ();
|
||||
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)
|
||||
{
|
||||
g_ptr_array_add (doc_array, uri);
|
||||
}
|
||||
|
||||
}
|
||||
g_list_free (docs);
|
||||
|
||||
if (doc_array->len)
|
||||
{
|
||||
guint i;
|
||||
|
||||
g_key_file_set_string_list (state_file, group_name,
|
||||
"documents",
|
||||
(const char **)doc_array->pdata,
|
||||
doc_array->len);
|
||||
for (i = 0; i < doc_array->len; i++)
|
||||
g_free (doc_array->pdata[i]);
|
||||
g_ptr_array_foreach (doc_array, (GFunc) g_free, NULL);
|
||||
}
|
||||
g_ptr_array_free (doc_array, TRUE);
|
||||
}
|
||||
|
@ -537,25 +551,29 @@ parse_window (GKeyFile *state_file, const char *group_name)
|
|||
"documents", NULL, NULL);
|
||||
if (documents)
|
||||
{
|
||||
int i;
|
||||
gint i;
|
||||
gboolean jump_to = FALSE;
|
||||
|
||||
for (i = 0; documents[i]; i++)
|
||||
{
|
||||
GFile *location;
|
||||
|
||||
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,
|
||||
"URI: %s (%s)",
|
||||
documents[i],
|
||||
jump_to ? "active" : "not active");
|
||||
xed_window_create_tab_from_uri (window,
|
||||
documents[i],
|
||||
NULL,
|
||||
0,
|
||||
FALSE,
|
||||
jump_to);
|
||||
|
||||
location = g_file_new_for_uri (documents[i]);
|
||||
xed_window_create_tab_from_location (window, location, NULL, 0, FALSE, jump_to);
|
||||
if (location)
|
||||
{
|
||||
g_object_unref (location);
|
||||
}
|
||||
}
|
||||
g_strfreev (documents);
|
||||
}
|
||||
|
|
156
xed/xed-tab.c
156
xed/xed-tab.c
|
@ -62,7 +62,7 @@ struct _XedTabPrivate
|
|||
XedPrintJob *print_job;
|
||||
|
||||
/* tmp data for saving */
|
||||
gchar *tmp_save_uri;
|
||||
GFile *tmp_save_location;
|
||||
|
||||
/* tmp data for loading */
|
||||
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
|
||||
xed_tab_finalize (GObject *object)
|
||||
{
|
||||
|
@ -222,8 +236,6 @@ xed_tab_finalize (GObject *object)
|
|||
g_timer_destroy (tab->priv->timer);
|
||||
}
|
||||
|
||||
g_free (tab->priv->tmp_save_uri);
|
||||
|
||||
if (tab->priv->auto_save_timeout > 0)
|
||||
{
|
||||
remove_auto_save_timeout (tab);
|
||||
|
@ -237,6 +249,7 @@ xed_tab_class_init (XedTabClass *klass)
|
|||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->dispose = xed_tab_dispose;
|
||||
object_class->finalize = xed_tab_finalize;
|
||||
object_class->get_property = xed_tab_get_property;
|
||||
object_class->set_property = xed_tab_set_property;
|
||||
|
@ -407,13 +420,13 @@ xed_tab_set_state (XedTab *tab,
|
|||
}
|
||||
|
||||
static void
|
||||
document_uri_notify_handler (XedDocument *document,
|
||||
document_location_notify_handler (XedDocument *document,
|
||||
GParamSpec *pspec,
|
||||
XedTab *tab)
|
||||
{
|
||||
xed_debug (DEBUG_TAB);
|
||||
|
||||
/* Notify the change in the URI */
|
||||
/* Notify the change in the location */
|
||||
g_object_notify (G_OBJECT (tab), "name");
|
||||
}
|
||||
|
||||
|
@ -478,7 +491,7 @@ io_loading_error_message_area_response (GtkWidget *message_area,
|
|||
{
|
||||
XedDocument *doc;
|
||||
XedView *view;
|
||||
gchar *uri;
|
||||
GFile *location;
|
||||
const XedEncoding *encoding;
|
||||
|
||||
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);
|
||||
g_return_if_fail (XED_IS_VIEW (view));
|
||||
|
||||
uri = xed_document_get_uri (doc);
|
||||
g_return_if_fail (uri != NULL);
|
||||
location = xed_document_get_location (doc);
|
||||
g_return_if_fail (location != NULL);
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
case GTK_RESPONSE_YES:
|
||||
/* 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);
|
||||
break;
|
||||
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);
|
||||
break;
|
||||
}
|
||||
|
||||
g_free (uri);
|
||||
g_object_unref (location);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -618,15 +631,15 @@ show_loading_message_area (XedTab *tab)
|
|||
}
|
||||
else
|
||||
{
|
||||
GFile *file;
|
||||
GFile *location;
|
||||
|
||||
file = xed_document_get_location (doc);
|
||||
if (file != NULL)
|
||||
location = xed_document_get_location (doc);
|
||||
if (location != NULL)
|
||||
{
|
||||
gchar *str;
|
||||
|
||||
str = xed_utils_location_get_dirname_for_display (file);
|
||||
g_object_unref (file);
|
||||
str = xed_utils_location_get_dirname_for_display (location);
|
||||
g_object_unref (location);
|
||||
|
||||
/* 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)".
|
||||
|
@ -704,7 +717,7 @@ show_saving_message_area (XedTab *tab)
|
|||
gchar *msg = NULL;
|
||||
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)
|
||||
{
|
||||
|
@ -734,7 +747,7 @@ show_saving_message_area (XedTab *tab)
|
|||
|
||||
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));
|
||||
g_free (to);
|
||||
|
@ -848,7 +861,6 @@ document_loaded (XedDocument *document,
|
|||
{
|
||||
GtkWidget *emsg;
|
||||
GFile *location;
|
||||
gchar *uri;
|
||||
const XedEncoding *encoding;
|
||||
|
||||
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);
|
||||
|
||||
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 (error != NULL && (error->domain != XED_DOCUMENT_ERROR || error->code != XED_DOCUMENT_ERROR_CONVERSION_FALLBACK))
|
||||
|
@ -892,11 +903,11 @@ document_loaded (XedDocument *document,
|
|||
}
|
||||
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)
|
||||
{
|
||||
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_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);
|
||||
|
||||
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_CALLBACK (unrecoverable_reverting_error_message_area_response), tab);
|
||||
|
@ -918,7 +929,6 @@ document_loaded (XedDocument *document,
|
|||
gtk_widget_show (emsg);
|
||||
|
||||
g_object_unref (location);
|
||||
g_free (uri);
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -928,10 +938,10 @@ document_loaded (XedDocument *document,
|
|||
GList *all_documents;
|
||||
GList *l;
|
||||
|
||||
g_return_if_fail (uri != NULL);
|
||||
g_return_if_fail (location != NULL);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
|
@ -976,7 +986,7 @@ document_loaded (XedDocument *document,
|
|||
|
||||
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);
|
||||
|
||||
|
@ -1009,7 +1019,6 @@ document_loaded (XedDocument *document,
|
|||
|
||||
end:
|
||||
g_object_unref (location);
|
||||
g_free (uri);
|
||||
|
||||
tab->priv->tmp_line_pos = 0;
|
||||
tab->priv->tmp_encoding = NULL;
|
||||
|
@ -1054,8 +1063,11 @@ static void
|
|||
end_saving (XedTab *tab)
|
||||
{
|
||||
/* Reset tmp data for saving */
|
||||
g_free (tab->priv->tmp_save_uri);
|
||||
tab->priv->tmp_save_uri = NULL;
|
||||
if (tab->priv->tmp_save_location)
|
||||
{
|
||||
g_object_unref (tab->priv->tmp_save_location);
|
||||
tab->priv->tmp_save_location = NULL;
|
||||
}
|
||||
tab->priv->tmp_encoding = NULL;
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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)
|
||||
{
|
||||
const XedEncoding *encoding;
|
||||
gchar *tmp_uri;
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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
|
||||
{
|
||||
|
@ -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->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->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)
|
||||
{
|
||||
/* 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);
|
||||
|
||||
set_message_area (tab, emsg);
|
||||
|
@ -1229,7 +1244,7 @@ document_saved (XedDocument *document,
|
|||
error->code == G_IO_ERROR_CANT_CREATE_BACKUP))
|
||||
{
|
||||
/* 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);
|
||||
|
||||
set_message_area (tab, emsg);
|
||||
|
@ -1243,9 +1258,9 @@ document_saved (XedDocument *document,
|
|||
error->code != G_IO_ERROR_PARTIAL_INPUT))
|
||||
{
|
||||
/* 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);
|
||||
|
||||
set_message_area (tab, emsg);
|
||||
|
@ -1258,7 +1273,7 @@ document_saved (XedDocument *document,
|
|||
/* This error is recoverable */
|
||||
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,
|
||||
error);
|
||||
|
||||
|
@ -1276,7 +1291,7 @@ document_saved (XedDocument *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);
|
||||
|
||||
if (tab->priv->print_preview != NULL)
|
||||
|
@ -1324,20 +1339,19 @@ display_externally_modified_notification (XedTab *tab)
|
|||
{
|
||||
GtkWidget *message_area;
|
||||
XedDocument *doc;
|
||||
gchar *uri;
|
||||
GFile *location;
|
||||
gboolean document_modified;
|
||||
|
||||
doc = xed_tab_get_document (tab);
|
||||
g_return_if_fail (XED_IS_DOCUMENT (doc));
|
||||
|
||||
/* uri cannot be NULL, we're here because
|
||||
* the file we're editing changed on disk */
|
||||
uri = xed_document_get_uri (doc);
|
||||
g_return_if_fail (uri != NULL);
|
||||
/* we're here because the file we're editing changed on disk */
|
||||
location = xed_document_get_location (doc);
|
||||
g_return_if_fail (location != NULL);
|
||||
|
||||
document_modified = gtk_text_buffer_get_modified (GTK_TEXT_BUFFER(doc));
|
||||
message_area = xed_externally_modified_message_area_new (uri, document_modified);
|
||||
g_free (uri);
|
||||
message_area = xed_externally_modified_message_area_new (location, document_modified);
|
||||
g_object_unref (location);
|
||||
|
||||
tab->priv->message_area = NULL;
|
||||
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_widget_show (sw);
|
||||
|
||||
g_signal_connect (doc, "notify::uri",
|
||||
G_CALLBACK (document_uri_notify_handler), tab);
|
||||
g_signal_connect (doc, "notify::location",
|
||||
G_CALLBACK (document_location_notify_handler), tab);
|
||||
g_signal_connect (doc, "notify::shortname",
|
||||
G_CALLBACK (document_shortname_notify_handler), tab);
|
||||
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
|
||||
not refer to an existing file */
|
||||
GtkWidget *
|
||||
_xed_tab_new_from_uri (const gchar *uri,
|
||||
_xed_tab_new_from_location (GFile *location,
|
||||
const XedEncoding *encoding,
|
||||
gint line_pos,
|
||||
gboolean create)
|
||||
{
|
||||
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 ());
|
||||
|
||||
_xed_tab_load (tab, uri, encoding, line_pos, create);
|
||||
_xed_tab_load (tab, location, encoding, line_pos, create);
|
||||
|
||||
return GTK_WIDGET (tab);
|
||||
}
|
||||
|
@ -1805,7 +1819,7 @@ xed_tab_get_from_document (XedDocument *doc)
|
|||
|
||||
void
|
||||
_xed_tab_load (XedTab *tab,
|
||||
const gchar *uri,
|
||||
GFile *location,
|
||||
const XedEncoding *encoding,
|
||||
gint line_pos,
|
||||
gboolean create)
|
||||
|
@ -1813,6 +1827,7 @@ _xed_tab_load (XedTab *tab,
|
|||
XedDocument *doc;
|
||||
|
||||
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);
|
||||
|
||||
doc = xed_tab_get_document (tab);
|
||||
|
@ -1828,14 +1843,14 @@ _xed_tab_load (XedTab *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
|
||||
_xed_tab_revert (XedTab *tab)
|
||||
{
|
||||
XedDocument *doc;
|
||||
gchar *uri;
|
||||
GFile *location;
|
||||
|
||||
g_return_if_fail (XED_IS_TAB (tab));
|
||||
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);
|
||||
|
||||
uri = xed_document_get_uri (doc);
|
||||
g_return_if_fail (uri != NULL);
|
||||
location = xed_document_get_location (doc);
|
||||
g_return_if_fail (location != NULL);
|
||||
|
||||
tab->priv->tmp_line_pos = 0;
|
||||
tab->priv->tmp_encoding = xed_document_get_encoding (doc);
|
||||
|
@ -1862,9 +1877,9 @@ _xed_tab_revert (XedTab *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
|
||||
|
@ -1877,7 +1892,7 @@ _xed_tab_save (XedTab *tab)
|
|||
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_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);
|
||||
|
||||
doc = xed_tab_get_document (tab);
|
||||
|
@ -1902,7 +1917,7 @@ _xed_tab_save (XedTab *tab)
|
|||
xed_tab_set_state (tab, XED_TAB_STATE_SAVING);
|
||||
|
||||
/* 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);
|
||||
|
||||
if (tab->priv->auto_save_timeout > 0)
|
||||
|
@ -1920,7 +1935,7 @@ xed_tab_auto_save (XedTab *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);
|
||||
|
||||
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);
|
||||
|
||||
/* 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);
|
||||
|
||||
/* 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
|
||||
_xed_tab_save_as (XedTab *tab,
|
||||
const gchar *uri,
|
||||
GFile *location,
|
||||
const XedEncoding *encoding,
|
||||
XedDocumentNewlineType newline_type)
|
||||
{
|
||||
|
@ -1989,9 +2004,10 @@ _xed_tab_save_as (XedTab *tab,
|
|||
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_SHOWING_PRINT_PREVIEW));
|
||||
g_return_if_fail (G_IS_FILE (location));
|
||||
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);
|
||||
|
||||
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
|
||||
* 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;
|
||||
|
||||
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
|
||||
same pattern. This can be changed once we break API for 3.0 */
|
||||
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"
|
||||
|
|
|
@ -57,9 +57,6 @@ typedef enum
|
|||
XED_TAB_NUM_OF_STATES /* This is not a valid state */
|
||||
} XedTabState;
|
||||
|
||||
/*
|
||||
* Type checking and casting macros
|
||||
*/
|
||||
#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_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_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 _XedTabPrivate XedTabPrivate;
|
||||
typedef struct _XedTabClass XedTabClass;
|
||||
|
||||
struct _XedTab
|
||||
{
|
||||
|
@ -83,43 +76,28 @@ struct _XedTab
|
|||
XedTabPrivate *priv;
|
||||
};
|
||||
|
||||
/*
|
||||
* Class definition
|
||||
*/
|
||||
typedef struct _XedTabClass XedTabClass;
|
||||
|
||||
struct _XedTabClass
|
||||
{
|
||||
GtkBoxClass parent_class;
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
* Public methods
|
||||
*/
|
||||
GType xed_tab_get_type (void) G_GNUC_CONST;
|
||||
|
||||
XedView *xed_tab_get_view (XedTab *tab);
|
||||
|
||||
/* This is only an helper function */
|
||||
XedDocument *xed_tab_get_document (XedTab *tab);
|
||||
|
||||
XedTab *xed_tab_get_from_document (XedDocument *doc);
|
||||
|
||||
XedTabState xed_tab_get_state (XedTab *tab);
|
||||
|
||||
gboolean xed_tab_get_auto_save_enabled
|
||||
(XedTab *tab);
|
||||
|
||||
void xed_tab_set_auto_save_enabled
|
||||
(XedTab *tab,
|
||||
gboolean xed_tab_get_auto_save_enabled (XedTab *tab);
|
||||
void xed_tab_set_auto_save_enabled (XedTab *tab,
|
||||
gboolean enable);
|
||||
|
||||
gint xed_tab_get_auto_save_interval
|
||||
(XedTab *tab);
|
||||
|
||||
void xed_tab_set_auto_save_interval
|
||||
(XedTab *tab,
|
||||
gint xed_tab_get_auto_save_interval (XedTab *tab);
|
||||
void xed_tab_set_auto_save_interval (XedTab *tab,
|
||||
gint interval);
|
||||
|
||||
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
|
||||
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,
|
||||
gint line_pos,
|
||||
gboolean create);
|
||||
|
@ -139,22 +117,20 @@ gchar *_xed_tab_get_name (XedTab *tab);
|
|||
gchar *_xed_tab_get_tooltips (XedTab *tab);
|
||||
GdkPixbuf *_xed_tab_get_icon (XedTab *tab);
|
||||
void _xed_tab_load (XedTab *tab,
|
||||
const gchar *uri,
|
||||
GFile *location,
|
||||
const XedEncoding *encoding,
|
||||
gint line_pos,
|
||||
gboolean create);
|
||||
void _xed_tab_revert (XedTab *tab);
|
||||
void _xed_tab_save (XedTab *tab);
|
||||
void _xed_tab_save_as (XedTab *tab,
|
||||
const gchar *uri,
|
||||
GFile *location,
|
||||
const XedEncoding *encoding,
|
||||
XedDocumentNewlineType newline_type);
|
||||
|
||||
void _xed_tab_print (XedTab *tab);
|
||||
void _xed_tab_print_preview (XedTab *tab);
|
||||
|
||||
void _xed_tab_mark_for_closing (XedTab *tab);
|
||||
|
||||
gboolean _xed_tab_can_close (XedTab *tab);
|
||||
|
||||
G_END_DECLS
|
||||
|
|
124
xed/xed-utils.c
124
xed/xed-utils.c
|
@ -64,48 +64,12 @@
|
|||
/**
|
||||
* 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
|
||||
xed_utils_uri_has_file_scheme (const gchar *uri)
|
||||
xed_utils_location_has_file_scheme (GFile *location)
|
||||
{
|
||||
GFile *gfile;
|
||||
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;
|
||||
return g_file_has_uri_scheme (location, "file");
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -325,19 +289,18 @@ xed_utils_set_atk_relation (GtkWidget *obj1,
|
|||
}
|
||||
|
||||
gboolean
|
||||
xed_utils_uri_exists (const gchar* text_uri)
|
||||
xed_utils_location_exists (GFile *location)
|
||||
{
|
||||
GFile *gfile;
|
||||
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 (gfile, NULL);
|
||||
|
||||
g_object_unref (gfile);
|
||||
res = g_file_query_exists (location, NULL);
|
||||
|
||||
xed_debug_message (DEBUG_UTILS, res ? "TRUE" : "FALSE");
|
||||
|
||||
|
@ -1042,20 +1005,27 @@ has_valid_scheme (const gchar *uri)
|
|||
}
|
||||
|
||||
gboolean
|
||||
xed_utils_is_valid_uri (const gchar *uri)
|
||||
xed_utils_is_valid_location (GFile *location)
|
||||
{
|
||||
const guchar *p;
|
||||
gchar *uri;
|
||||
gboolean is_valid;
|
||||
|
||||
if (uri == NULL)
|
||||
if (location == NULL)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
uri = g_file_get_uri (location);
|
||||
|
||||
if (!has_valid_scheme (uri))
|
||||
{
|
||||
g_free (uri);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
is_valid = TRUE;
|
||||
|
||||
/* We expect to have a fully valid set of characters */
|
||||
for (p = (const guchar *)uri; *p; p++)
|
||||
{
|
||||
|
@ -1064,25 +1034,30 @@ xed_utils_is_valid_uri (const gchar *uri)
|
|||
++p;
|
||||
if (!g_ascii_isxdigit (*p))
|
||||
{
|
||||
return FALSE;
|
||||
is_valid = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
++p;
|
||||
if (!g_ascii_isxdigit (*p))
|
||||
{
|
||||
return FALSE;
|
||||
is_valid = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (*p <= 32 || *p >= 128)
|
||||
{
|
||||
return FALSE;
|
||||
is_valid = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
g_free (uri);
|
||||
|
||||
return is_valid;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
if (xed_utils_is_valid_location (gfile))
|
||||
{
|
||||
uri = g_file_get_uri (gfile);
|
||||
g_object_unref (gfile);
|
||||
|
||||
if (xed_utils_is_valid_uri (uri))
|
||||
{
|
||||
return uri;
|
||||
}
|
||||
|
||||
g_free (uri);
|
||||
g_object_unref (gfile);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -1286,26 +1261,26 @@ xed_utils_file_has_parent (GFile *gfile)
|
|||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
gchar *
|
||||
xed_utils_basename_for_display (gchar const *uri)
|
||||
xed_utils_basename_for_display (GFile *location)
|
||||
{
|
||||
gchar *name;
|
||||
GFile *gfile;
|
||||
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 */
|
||||
if (g_file_has_uri_scheme (gfile, "file"))
|
||||
if (xed_utils_location_has_file_scheme (location))
|
||||
{
|
||||
GFileInfo *info;
|
||||
info = g_file_query_info (gfile,
|
||||
info = g_file_query_info (location,
|
||||
G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME,
|
||||
G_FILE_QUERY_INFO_NONE,
|
||||
NULL,
|
||||
|
@ -1323,12 +1298,12 @@ xed_utils_basename_for_display (gchar const *uri)
|
|||
* g_filename_display_basename on the 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);
|
||||
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)
|
||||
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 *base;
|
||||
|
||||
parse_name = g_file_get_parse_name (gfile);
|
||||
parse_name = g_file_get_parse_name (location);
|
||||
base = g_filename_display_basename (parse_name);
|
||||
name = g_uri_unescape_string (base, NULL);
|
||||
|
||||
|
@ -1365,14 +1340,14 @@ xed_utils_basename_for_display (gchar const *uri)
|
|||
g_free (hn);
|
||||
}
|
||||
|
||||
g_object_unref (gfile);
|
||||
g_free (uri);
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* 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.
|
||||
*/
|
||||
gchar *
|
||||
xed_utils_uri_for_display (const gchar *uri)
|
||||
xed_utils_uri_for_display (GFile *location)
|
||||
{
|
||||
GFile *gfile;
|
||||
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;
|
||||
return g_file_get_parse_name (location);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -48,8 +48,7 @@ G_BEGIN_DECLS
|
|||
|
||||
enum { XED_ALL_WORKSPACES = 0xffffffff };
|
||||
|
||||
gboolean xed_utils_uri_has_writable_scheme (const gchar *uri);
|
||||
gboolean xed_utils_uri_has_file_scheme (const gchar *uri);
|
||||
gboolean xed_utils_location_has_file_scheme (GFile *location);
|
||||
|
||||
void xed_utils_menu_position_under_widget (GtkMenu *menu,
|
||||
gint *x,
|
||||
|
@ -87,7 +86,7 @@ void xed_utils_set_atk_relation (GtkWidget *obj1,
|
|||
GtkWidget *obj2,
|
||||
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);
|
||||
|
||||
|
@ -114,7 +113,7 @@ void xed_utils_get_current_viewport (GdkScreen *screen,
|
|||
gint *x,
|
||||
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,
|
||||
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 */
|
||||
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,
|
||||
gchar **scheme,
|
||||
|
|
|
@ -43,14 +43,20 @@
|
|||
/* Signals */
|
||||
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 };
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0, PROP_STATE
|
||||
PROP_0,
|
||||
PROP_STATE
|
||||
};
|
||||
|
||||
enum
|
||||
|
@ -842,11 +848,12 @@ update_languages_menu (XedWindow *window)
|
|||
|
||||
void
|
||||
_xed_recent_add (XedWindow *window,
|
||||
const gchar *uri,
|
||||
GFile *location,
|
||||
const gchar *mime)
|
||||
{
|
||||
GtkRecentManager *recent_manager;
|
||||
GtkRecentData *recent_data;
|
||||
gchar *uri;
|
||||
|
||||
static gchar *groups[2] = { "xed", NULL };
|
||||
|
||||
|
@ -862,8 +869,11 @@ _xed_recent_add (XedWindow *window,
|
|||
recent_data->groups = groups;
|
||||
recent_data->is_private = FALSE;
|
||||
|
||||
uri = g_file_get_uri (location);
|
||||
|
||||
gtk_recent_manager_add_full (recent_manager, uri, recent_data);
|
||||
|
||||
g_free (uri);
|
||||
g_free (recent_data->app_exec);
|
||||
|
||||
g_slice_free(GtkRecentData, recent_data);
|
||||
|
@ -871,29 +881,32 @@ _xed_recent_add (XedWindow *window,
|
|||
|
||||
void
|
||||
_xed_recent_remove (XedWindow *window,
|
||||
const gchar *uri)
|
||||
GFile *location)
|
||||
{
|
||||
GtkRecentManager *recent_manager;
|
||||
gchar *uri;
|
||||
|
||||
recent_manager = gtk_recent_manager_get_default ();
|
||||
|
||||
uri = g_file_get_uri (location);
|
||||
gtk_recent_manager_remove_item (recent_manager, uri, NULL);
|
||||
g_free (uri);
|
||||
}
|
||||
|
||||
static void
|
||||
open_recent_file (const gchar *uri,
|
||||
open_recent_file (GFile *location,
|
||||
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
|
||||
|
@ -901,14 +914,20 @@ recents_menu_activate (GtkAction *action,
|
|||
XedWindow *window)
|
||||
{
|
||||
GtkRecentInfo *info;
|
||||
GFile *location;
|
||||
const gchar *uri;
|
||||
|
||||
info = g_object_get_data (G_OBJECT (action), "gtk-recent-info");
|
||||
g_return_if_fail (info != NULL);
|
||||
|
||||
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
|
||||
|
@ -994,6 +1013,7 @@ update_recent_files_menu (XedWindow *window)
|
|||
gchar *tip;
|
||||
GtkAction *action;
|
||||
GtkRecentInfo *info = l->data;
|
||||
GFile *location;
|
||||
|
||||
/* clamp */
|
||||
if (i >= max_recents)
|
||||
|
@ -1017,7 +1037,9 @@ update_recent_files_menu (XedWindow *window)
|
|||
|
||||
/* gtk_recent_info_get_uri_display (info) is buggy and
|
||||
* 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);
|
||||
g_free (uri);
|
||||
|
||||
|
@ -2382,7 +2404,7 @@ static void
|
|||
load_uris_from_drop (XedWindow *window,
|
||||
gchar **uri_list)
|
||||
{
|
||||
GSList *uris = NULL;
|
||||
GSList *locations = NULL;
|
||||
gint i;
|
||||
|
||||
if (uri_list == NULL)
|
||||
|
@ -2392,13 +2414,14 @@ load_uris_from_drop (XedWindow *window,
|
|||
|
||||
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);
|
||||
xed_commands_load_uris (window, uris, NULL, 0);
|
||||
locations = g_slist_reverse (locations);
|
||||
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 */
|
||||
|
@ -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
|
||||
* @uri: the uri of the document
|
||||
* @location: the location of the document
|
||||
* @encoding: a #XedEncoding
|
||||
* @line_pos: the line position to visualize
|
||||
* @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
|
||||
*/
|
||||
XedTab *
|
||||
xed_window_create_tab_from_uri (XedWindow *window,
|
||||
const gchar *uri,
|
||||
xed_window_create_tab_from_location (XedWindow *window,
|
||||
GFile *location,
|
||||
const XedEncoding *encoding,
|
||||
gint line_pos,
|
||||
gboolean create,
|
||||
|
@ -3622,9 +3645,9 @@ xed_window_create_tab_from_uri (XedWindow *window,
|
|||
GtkWidget *tab;
|
||||
|
||||
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)
|
||||
{
|
||||
return NULL;
|
||||
|
|
|
@ -20,9 +20,6 @@ typedef enum
|
|||
XED_WINDOW_STATE_SAVING_SESSION = 1 << 5
|
||||
} XedWindowState;
|
||||
|
||||
/*
|
||||
* Type checking and casting macros
|
||||
*/
|
||||
#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_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_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 _XedWindowPrivate XedWindowPrivate;
|
||||
typedef struct _XedWindowClass XedWindowClass;
|
||||
|
||||
struct _XedWindow
|
||||
{
|
||||
|
@ -46,11 +39,6 @@ struct _XedWindow
|
|||
XedWindowPrivate *priv;
|
||||
};
|
||||
|
||||
/*
|
||||
* Class definition
|
||||
*/
|
||||
typedef struct _XedWindowClass XedWindowClass;
|
||||
|
||||
struct _XedWindowClass
|
||||
{
|
||||
GtkWindowClass parent_class;
|
||||
|
@ -68,7 +56,7 @@ struct _XedWindowClass
|
|||
*/
|
||||
GType xed_window_get_type (void) G_GNUC_CONST;
|
||||
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);
|
||||
void xed_window_close_tab (XedWindow *window, XedTab *tab);
|
||||
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);
|
||||
|
||||
/* these are in xed-window because of screen safety */
|
||||
void _xed_recent_add (XedWindow *window, const gchar *uri, const gchar *mime);
|
||||
void _xed_recent_remove (XedWindow *window, const gchar *uri);
|
||||
void _xed_recent_add (XedWindow *window, GFile *location, const gchar *mime);
|
||||
void _xed_recent_remove (XedWindow *window, GFile *location);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
|
Loading…
Reference in New Issue