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

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

View File

@ -535,6 +535,7 @@ init_bookmarks (XedFileBookmarksStore * model)
{
if (**line)
{
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);
}

View File

@ -80,7 +80,7 @@ GType xed_file_bookmarks_store_get_type (void) G_GNUC_CONST;
void _xed_file_bookmarks_store_register_type (GTypeModule *type_module);
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);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View 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);

View File

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

View File

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

View File

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

View File

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

View File

@ -80,12 +80,12 @@ PROFILE (static GTimer *timer = NULL)
#define XED_DOCUMENT_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), XED_TYPE_DOCUMENT, XedDocumentPrivate))
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);
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -180,7 +180,7 @@ static gboolean
parse_gio_error (gint code,
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

View File

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

View File

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

View File

@ -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 ();
}

View File

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

View File

@ -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);
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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