filechooserbutton: Stop using GtkFileSystem

Just use gio directly.
This commit is contained in:
Matthias Clasen 2020-07-11 21:40:06 -04:00
parent 0210850e86
commit b41d380230

View File

@ -192,11 +192,10 @@ struct _GtkFileChooserButton
GtkTreeModel *model;
GtkTreeModel *filter_model;
GtkFileSystem *fs;
GFile *selection_while_inactive;
GFile *current_folder_while_inactive;
gulong fs_volumes_changed_id;
GVolumeMonitor *volume_monitor;
GCancellable *dnd_select_folder_cancellable;
GCancellable *update_button_cancellable;
@ -276,7 +275,7 @@ static void gtk_file_chooser_button_state_flags_changed (GtkWidget
GtkStateFlags previous_state);
/* Utility Functions */
static void set_info_for_file_at_iter (GtkFileChooserButton *fs,
static void set_info_for_file_at_iter (GtkFileChooserButton *button,
GFile *file,
GtkTreeIter *iter);
@ -313,8 +312,6 @@ static void update_combo_box (GtkFileChooserButton *button)
static void update_label_and_image (GtkFileChooserButton *button);
/* Child Object Callbacks */
static void fs_volumes_changed_cb (GtkFileSystem *fs,
gpointer user_data);
static void bookmarks_changed_cb (gpointer user_data);
static void combo_box_changed_cb (GtkComboBox *combo_box,
@ -329,6 +326,10 @@ static void dialog_response_cb (GtkDialog *dialog,
static void native_response_cb (GtkFileChooserNative *native,
gint response,
gpointer user_data);
static void volumes_changed (GVolumeMonitor *volume_monitor,
gpointer volume,
gpointer user_data);
static GSList * get_volumes_list (GVolumeMonitor *volume_monitor);
static guint file_chooser_button_signals[LAST_SIGNAL] = { 0 };
@ -342,9 +343,9 @@ G_DEFINE_TYPE_WITH_CODE (GtkFileChooserButton, gtk_file_chooser_button, GTK_TYPE
struct DndSelectFolderData
{
GtkFileSystem *file_system;
GtkFileChooserButton *button;
GtkFileChooserAction action;
GCancellable *cancellable;
GFile *file;
gchar **uris;
guint i;
@ -352,29 +353,29 @@ struct DndSelectFolderData
};
static void
dnd_select_folder_get_info_cb (GCancellable *cancellable,
GFileInfo *info,
const GError *error,
dnd_select_folder_get_info_cb (GObject *object,
GAsyncResult *result,
gpointer user_data)
{
GFile *file = G_FILE (object);
struct DndSelectFolderData *data = user_data;
GFileInfo *info;
GtkFileChooserButton *button = data->button;
gboolean cancelled = g_cancellable_is_cancelled (cancellable);
if (cancellable != button->dnd_select_folder_cancellable)
if (g_cancellable_is_cancelled (data->cancellable))
{
g_object_unref (data->button);
g_object_unref (data->file);
g_object_unref (data->cancellable);
g_strfreev (data->uris);
g_free (data);
g_object_unref (cancellable);
return;
}
button->dnd_select_folder_cancellable = NULL;
if (!cancelled && !error && info != NULL)
info = g_file_query_info_finish (file, result, NULL);
if (info)
{
gboolean is_folder;
@ -388,16 +389,18 @@ dnd_select_folder_get_info_cb (GCancellable *cancellable,
else
data->selected = FALSE;
g_clear_object (&info);
if (data->selected || data->uris[++data->i] == NULL)
{
g_signal_emit (data->button, file_chooser_button_signals[FILE_SET], 0);
g_object_unref (data->button);
g_object_unref (data->file);
g_object_unref (data->cancellable);
g_strfreev (data->uris);
g_free (data);
g_object_unref (cancellable);
return;
}
@ -406,12 +409,17 @@ dnd_select_folder_get_info_cb (GCancellable *cancellable,
data->file = g_file_new_for_uri (data->uris[data->i]);
button->dnd_select_folder_cancellable =
_gtk_file_system_get_info (data->file_system, data->file,
"standard::type",
dnd_select_folder_get_info_cb, user_data);
g_clear_object (&data->cancellable);
data->cancellable = g_cancellable_new ();
button->dnd_select_folder_cancellable = data->cancellable;
g_object_unref (cancellable);
g_file_query_info_async (data->file,
"standard::type",
G_FILE_QUERY_INFO_NONE,
G_PRIORITY_DEFAULT,
data->cancellable,
dnd_select_folder_get_info_cb,
user_data);
}
static gboolean
@ -431,18 +439,21 @@ gtk_file_chooser_button_drop (GtkDropTarget *target,
info->i = 0;
info->uris = g_new0 (char *, 2);
info->selected = FALSE;
info->file_system = button->fs;
g_object_get (button->chooser, "action", &info->action, NULL);
info->file = g_object_ref (file);
if (button->dnd_select_folder_cancellable)
g_cancellable_cancel (button->dnd_select_folder_cancellable);
g_clear_pointer (&button->dnd_select_folder_cancellable, g_cancellable_cancel);
button->dnd_select_folder_cancellable =
_gtk_file_system_get_info (button->fs, info->file,
info->cancellable = g_cancellable_new ();
button->dnd_select_folder_cancellable = info->cancellable;
g_file_query_info_async (info->file,
"standard::type",
dnd_select_folder_get_info_cb, info);
G_FILE_QUERY_INFO_NONE,
G_PRIORITY_DEFAULT,
info->cancellable,
dnd_select_folder_get_info_cb,
info);
return TRUE;
}
@ -900,14 +911,31 @@ gtk_file_chooser_button_constructed (GObject *object)
* delegated when the OK button is pressed. */
g_object_set_qdata (object, GTK_FILE_CHOOSER_DELEGATE_QUARK, button->chooser);
button->fs =
g_object_ref (_gtk_file_chooser_get_file_system (button->chooser));
model_add_special (button);
list = _gtk_file_system_list_volumes (button->fs);
button->volume_monitor = g_volume_monitor_get ();
g_signal_connect (button->volume_monitor, "mount-added",
G_CALLBACK (volumes_changed), button);
g_signal_connect (button->volume_monitor, "mount-removed",
G_CALLBACK (volumes_changed), button);
g_signal_connect (button->volume_monitor, "mount-changed",
G_CALLBACK (volumes_changed), button);
g_signal_connect (button->volume_monitor, "volume-added",
G_CALLBACK (volumes_changed), button);
g_signal_connect (button->volume_monitor, "volume-removed",
G_CALLBACK (volumes_changed), button);
g_signal_connect (button->volume_monitor, "volume-changed",
G_CALLBACK (volumes_changed), button);
g_signal_connect (button->volume_monitor, "drive-connected",
G_CALLBACK (volumes_changed), button);
g_signal_connect (button->volume_monitor, "drive-disconnected",
G_CALLBACK (volumes_changed), button);
g_signal_connect (button->volume_monitor, "drive-changed",
G_CALLBACK (volumes_changed), button);
list = get_volumes_list (button->volume_monitor);
model_add_volumes (button, list);
g_slist_free (list);
g_slist_free_full (list, g_object_unref);
list = _gtk_bookmarks_manager_list_bookmarks (button->bookmarks_manager);
model_add_bookmarks (button, list);
@ -932,10 +960,6 @@ gtk_file_chooser_button_constructed (GObject *object)
"action", gtk_file_chooser_get_action (GTK_FILE_CHOOSER (button->chooser)),
NULL);
button->fs_volumes_changed_id =
g_signal_connect (button->fs, "volumes-changed",
G_CALLBACK (fs_volumes_changed_cb), object);
update_label_and_image (button);
update_combo_box (button);
}
@ -1091,7 +1115,6 @@ static void
gtk_file_chooser_button_dispose (GObject *object)
{
GtkFileChooserButton *button = GTK_FILE_CHOOSER_BUTTON (object);
GSList *l;
if (button->model)
{
@ -1110,24 +1133,14 @@ gtk_file_chooser_button_dispose (GObject *object)
g_clear_pointer (&button->dnd_select_folder_cancellable, g_cancellable_cancel);
g_clear_pointer (&button->update_button_cancellable, g_cancellable_cancel);
if (button->change_icon_theme_cancellables)
{
for (l = button->change_icon_theme_cancellables; l; l = l->next)
{
GCancellable *cancellable = G_CANCELLABLE (l->data);
g_cancellable_cancel (cancellable);
}
g_slist_free (button->change_icon_theme_cancellables);
g_slist_free_full (button->change_icon_theme_cancellables, (GDestroyNotify)g_cancellable_cancel);
button->change_icon_theme_cancellables = NULL;
}
g_clear_object (&button->filter_model);
if (button->fs)
{
g_signal_handler_disconnect (button->fs, button->fs_volumes_changed_id);
g_clear_object (&button->fs);
}
if (button->volume_monitor)
g_signal_handlers_disconnect_by_func (button->volume_monitor, volumes_changed, button);
g_clear_object (&button->volume_monitor);
g_clear_pointer (&button->bookmarks_manager, _gtk_bookmarks_manager_free);
@ -1194,26 +1207,34 @@ struct ChangeIconThemeData
{
GtkFileChooserButton *button;
GtkTreeRowReference *row_ref;
GCancellable *cancellable;
};
static void
change_icon_theme_get_info_cb (GCancellable *cancellable,
GFileInfo *info,
const GError *error,
change_icon_theme_get_info_cb (GObject *source,
GAsyncResult *result,
gpointer user_data)
{
gboolean cancelled = g_cancellable_is_cancelled (cancellable);
GIcon *icon;
GFile *file = G_FILE (source);
struct ChangeIconThemeData *data = user_data;
GFileInfo *info;
GIcon *icon;
GtkFileChooserButton *button = data->button;
if (!g_slist_find (button->change_icon_theme_cancellables, cancellable))
goto out;
if (g_cancellable_is_cancelled (data->cancellable))
{
g_object_unref (data->button);
g_object_unref (data->cancellable);
gtk_tree_row_reference_free (data->row_ref);
g_free (data);
return;
}
button->change_icon_theme_cancellables =
g_slist_remove (button->change_icon_theme_cancellables, cancellable);
g_slist_remove (button->change_icon_theme_cancellables, data->cancellable);
if (cancelled || error)
info = g_file_query_info_finish (file, result, NULL);
if (!info)
goto out;
icon = _gtk_file_info_get_icon (info, ICON_SIZE, gtk_widget_get_scale_factor (GTK_WIDGET (data->button)));
@ -1244,25 +1265,20 @@ change_icon_theme_get_info_cb (GCancellable *cancellable,
out:
g_object_unref (data->button);
g_object_unref (data->cancellable);
gtk_tree_row_reference_free (data->row_ref);
g_free (data);
g_object_unref (cancellable);
g_clear_object (&info);
}
static void
change_icon_theme (GtkFileChooserButton *button)
{
GtkTreeIter iter;
GSList *l;
gint width = 0;
for (l = button->change_icon_theme_cancellables; l; l = l->next)
{
GCancellable *cancellable = G_CANCELLABLE (l->data);
g_cancellable_cancel (cancellable);
}
g_slist_free (button->change_icon_theme_cancellables);
g_slist_free_full (button->change_icon_theme_cancellables, (GDestroyNotify)g_cancellable_cancel);
button->change_icon_theme_cancellables = NULL;
update_label_and_image (button);
@ -1292,7 +1308,6 @@ change_icon_theme (GtkFileChooserButton *button)
if (g_file_is_native (G_FILE (data)))
{
GtkTreePath *path;
GCancellable *cancellable;
struct ChangeIconThemeData *info;
info = g_new0 (struct ChangeIconThemeData, 1);
@ -1301,13 +1316,17 @@ change_icon_theme (GtkFileChooserButton *button)
info->row_ref = gtk_tree_row_reference_new (button->model, path);
gtk_tree_path_free (path);
cancellable =
_gtk_file_system_get_info (button->fs, data,
info->cancellable = g_cancellable_new ();
g_file_query_info_async (data,
"standard::icon",
G_FILE_QUERY_INFO_NONE,
G_PRIORITY_DEFAULT,
info->cancellable,
change_icon_theme_get_info_cb,
info);
button->change_icon_theme_cancellables =
g_slist_append (button->change_icon_theme_cancellables, cancellable);
g_slist_append (button->change_icon_theme_cancellables, info->cancellable);
icon = NULL;
}
else
@ -1322,9 +1341,14 @@ change_icon_theme (GtkFileChooserButton *button)
}
break;
case ROW_TYPE_VOLUME:
if (data)
icon = _gtk_file_system_volume_get_icon (data);
if (G_IS_DRIVE (data))
icon = g_drive_get_icon (G_DRIVE (data));
else if (G_IS_VOLUME (data))
icon = g_volume_get_icon (G_VOLUME (data));
else if (G_IS_MOUNT (data))
icon = g_mount_get_icon (G_MOUNT (data));
else
icon = NULL;
break;
default:
continue;
@ -1370,17 +1394,17 @@ struct SetDisplayNameData
};
static void
set_info_get_info_cb (GCancellable *cancellable,
GFileInfo *info,
const GError *error,
set_info_get_info_cb (GObject *source,
GAsyncResult *result,
gpointer callback_data)
{
gboolean cancelled = g_cancellable_is_cancelled (cancellable);
GFile *file = G_FILE (source);
struct SetDisplayNameData *data = callback_data;
GFileInfo *info = NULL;
GIcon *icon;
GtkTreePath *path;
GtkTreeIter iter;
GCancellable *model_cancellable = NULL;
struct SetDisplayNameData *data = callback_data;
GtkFileChooserButton *button = data->button;
gboolean is_folder;
@ -1400,15 +1424,13 @@ set_info_get_info_cb (GCancellable *cancellable,
gtk_tree_model_get (button->model, &iter,
CANCELLABLE_COLUMN, &model_cancellable,
-1);
if (cancellable != model_cancellable)
goto out;
gtk_list_store_set (GTK_LIST_STORE (button->model), &iter,
CANCELLABLE_COLUMN, NULL,
-1);
if (cancelled || error)
/* There was an error, leave the fallback name in there */
info = g_file_query_info_finish (file, result, NULL);
if (!info)
goto out;
icon = _gtk_file_info_get_icon (info, ICON_SIZE, gtk_widget_get_scale_factor (GTK_WIDGET (data->button)));
@ -1433,7 +1455,7 @@ out:
gtk_tree_row_reference_free (data->row_ref);
g_free (data);
g_object_unref (cancellable);
g_clear_object (&info);
}
static void
@ -1453,9 +1475,14 @@ set_info_for_file_at_iter (GtkFileChooserButton *button,
data->row_ref = gtk_tree_row_reference_new (button->model, tree_path);
gtk_tree_path_free (tree_path);
cancellable = _gtk_file_system_get_info (button->fs, file,
cancellable = g_cancellable_new ();
g_file_query_info_async (file,
"standard::type,standard::icon,standard::display-name",
set_info_get_info_cb, data);
G_FILE_QUERY_INFO_NONE,
G_PRIORITY_DEFAULT,
cancellable,
set_info_get_info_cb,
data);
gtk_list_store_set (GTK_LIST_STORE (button->model), iter,
CANCELLABLE_COLUMN, cancellable,
@ -1541,10 +1568,8 @@ model_free_row_data (GtkFileChooserButton *button,
case ROW_TYPE_SHORTCUT:
case ROW_TYPE_BOOKMARK:
case ROW_TYPE_CURRENT_FOLDER:
g_object_unref (data);
break;
case ROW_TYPE_VOLUME:
_gtk_file_system_volume_unref (data);
g_object_unref (data);
break;
default:
break;
@ -1552,18 +1577,18 @@ model_free_row_data (GtkFileChooserButton *button,
}
static void
model_add_special_get_info_cb (GCancellable *cancellable,
GFileInfo *info,
const GError *error,
model_add_special_get_info_cb (GObject *source,
GAsyncResult *result,
gpointer user_data)
{
gboolean cancelled = g_cancellable_is_cancelled (cancellable);
GFile *file = G_FILE (source);
struct ChangeIconThemeData *data = user_data;
GtkTreeIter iter;
GtkTreePath *path;
GIcon *icon;
GCancellable *model_cancellable = NULL;
struct ChangeIconThemeData *data = user_data;
GtkFileChooserButton *button = data->button;
GFileInfo *info = NULL;
gchar *name;
if (!button->model)
@ -1581,15 +1606,13 @@ model_add_special_get_info_cb (GCancellable *cancellable,
gtk_tree_model_get (button->model, &iter,
CANCELLABLE_COLUMN, &model_cancellable,
-1);
if (cancellable != model_cancellable)
goto out;
gtk_list_store_set (GTK_LIST_STORE (button->model), &iter,
CANCELLABLE_COLUMN, NULL,
-1);
if (cancelled || error)
info = g_file_query_info_finish (file, result, NULL);
if (!info)
goto out;
icon = _gtk_file_info_get_icon (info, ICON_SIZE, gtk_widget_get_scale_factor (GTK_WIDGET (data->button)));
@ -1615,7 +1638,7 @@ out:
gtk_tree_row_reference_free (data->row_ref);
g_free (data);
g_object_unref (cancellable);
g_clear_object (&info);
}
static void
@ -1650,9 +1673,14 @@ model_add_special (GtkFileChooserButton *button)
tree_path);
gtk_tree_path_free (tree_path);
cancellable = _gtk_file_system_get_info (button->fs, file,
cancellable = g_cancellable_new ();
g_file_query_info_async (file,
"standard::icon,standard::display-name",
model_add_special_get_info_cb, info);
G_FILE_QUERY_INFO_NONE,
G_PRIORITY_DEFAULT,
cancellable,
model_add_special_get_info_cb,
info);
gtk_list_store_set (store, &iter,
ICON_COLUMN, NULL,
@ -1688,9 +1716,14 @@ model_add_special (GtkFileChooserButton *button)
tree_path);
gtk_tree_path_free (tree_path);
cancellable = _gtk_file_system_get_info (button->fs, file,
cancellable = g_cancellable_new ();
g_file_query_info_async (file,
"standard::icon,standard::display-name",
model_add_special_get_info_cb, info);
G_FILE_QUERY_INFO_NONE,
G_PRIORITY_DEFAULT,
cancellable,
model_add_special_get_info_cb,
info);
gtk_list_store_set (store, &iter,
TYPE_COLUMN, ROW_TYPE_SPECIAL,
@ -1721,26 +1754,43 @@ model_add_volumes (GtkFileChooserButton *button,
for (l = volumes; l; l = l->next)
{
GtkFileSystemVolume *volume;
gpointer *volume;
GtkTreeIter iter;
GIcon *icon;
gchar *display_name;
volume = l->data;
icon = _gtk_file_system_volume_get_icon (volume);
display_name = _gtk_file_system_volume_get_display_name (volume);
if (G_IS_DRIVE (volume))
{
icon = g_drive_get_icon (G_DRIVE (volume));
display_name = g_drive_get_name (G_DRIVE (volume));
}
else if (G_IS_VOLUME (volume))
{
icon = g_volume_get_icon (G_VOLUME (volume));
display_name = g_volume_get_name (G_VOLUME (volume));
}
else if (G_IS_MOUNT (volume))
{
icon = g_mount_get_icon (G_MOUNT (volume));
display_name = g_mount_get_name (G_MOUNT (volume));
}
else
{
icon = NULL;
display_name = NULL;
}
gtk_list_store_insert (store, &iter, pos);
gtk_list_store_set (store, &iter,
ICON_COLUMN, icon,
DISPLAY_NAME_COLUMN, display_name,
TYPE_COLUMN, ROW_TYPE_VOLUME,
DATA_COLUMN, _gtk_file_system_volume_ref (volume),
DATA_COLUMN, g_object_ref (volume),
IS_FOLDER_COLUMN, TRUE,
-1);
if (icon)
g_object_unref (icon);
g_clear_object (&icon);
g_free (display_name);
button->n_volumes++;
@ -1978,8 +2028,7 @@ model_remove_rows (GtkFileChooserButton *button,
/* Filter Model */
static gboolean
test_if_file_is_visible (GtkFileSystem *fs,
GFile *file,
test_if_file_is_visible (GFile *file,
gboolean is_folder)
{
if (!file)
@ -1996,7 +2045,6 @@ filter_model_visible_func (GtkTreeModel *model,
GtkTreeIter *iter,
gpointer user_data)
{
GtkFileChooserButton *button = GTK_FILE_CHOOSER_BUTTON (user_data);
gchar type;
gpointer data;
gboolean retval, is_folder;
@ -2018,7 +2066,7 @@ filter_model_visible_func (GtkTreeModel *model,
case ROW_TYPE_SPECIAL:
case ROW_TYPE_SHORTCUT:
case ROW_TYPE_BOOKMARK:
retval = test_if_file_is_visible (button->fs, data, is_folder);
retval = test_if_file_is_visible (data, is_folder);
break;
case ROW_TYPE_VOLUME:
retval = TRUE;
@ -2118,15 +2166,10 @@ update_combo_box (GtkFileChooserButton *button)
break;
case ROW_TYPE_VOLUME:
{
GFile *base_file;
base_file = _gtk_file_system_volume_get_root (data);
if (base_file)
{
GFile *base_file = g_file_new_for_uri ("file:///");
row_found = (file && g_file_equal (base_file, file));
g_object_unref (base_file);
}
}
break;
default:
row_found = FALSE;
@ -2171,21 +2214,19 @@ update_combo_box (GtkFileChooserButton *button)
/* Button */
static void
update_label_get_info_cb (GCancellable *cancellable,
GFileInfo *info,
const GError *error,
update_label_get_info_cb (GObject *source,
GAsyncResult *result,
gpointer data)
{
gboolean cancelled = g_cancellable_is_cancelled (cancellable);
GIcon *icon;
GFile *file = G_FILE (source);
GtkFileChooserButton *button = data;
GIcon *icon;
GFileInfo *info;
if (cancellable != button->update_button_cancellable)
goto out;
g_clear_object (&button->update_button_cancellable);
button->update_button_cancellable = NULL;
if (cancelled || error)
info = g_file_query_info_finish (file, result, NULL);
if (!info)
goto out;
gtk_label_set_text (GTK_LABEL (button->label), g_file_info_get_display_name (info));
@ -2199,8 +2240,8 @@ update_label_get_info_cb (GCancellable *cancellable,
out:
emit_selection_changed_if_changing_selection (button);
g_clear_object (&info);
g_object_unref (button);
g_object_unref (cancellable);
}
static void
@ -2223,44 +2264,46 @@ update_label_and_image (GtkFileChooserButton *button)
if (file)
{
GtkFileSystemVolume *volume = NULL;
volume = _gtk_file_system_get_volume_for_file (button->fs, file);
if (volume)
{
GMount *mount;
GFile *base_file;
base_file = _gtk_file_system_volume_get_root (volume);
mount = g_file_find_enclosing_mount (file, NULL, NULL);
if (!mount && g_file_is_native (file))
base_file = g_file_new_for_uri ("file:///");
else if (mount)
base_file = g_mount_get_root (mount);
else
base_file = NULL;
if (base_file && g_file_equal (base_file, file))
{
GIcon *icon;
label_text = _gtk_file_system_volume_get_display_name (volume);
icon = _gtk_file_system_volume_get_icon (volume);
label_text = g_mount_get_name (mount);
icon = g_mount_get_icon (mount);
gtk_image_set_from_gicon (GTK_IMAGE (button->image), icon);
gtk_image_set_pixel_size (GTK_IMAGE (button->image), ICON_SIZE);
if (icon)
g_object_unref (icon);
g_clear_object (&icon);
}
if (base_file)
g_object_unref (base_file);
_gtk_file_system_volume_unref (volume);
g_clear_object (&base_file);
g_clear_object (&mount);
if (label_text)
{
done_changing_selection = TRUE;
goto out;
}
}
if (g_file_is_native (file) ||
!_gtk_bookmarks_manager_has_bookmark (button->bookmarks_manager, file))
{
button->update_button_cancellable =
_gtk_file_system_get_info (button->fs, file,
button->update_button_cancellable = g_cancellable_new ();
g_file_query_info_async (file,
"standard::icon,standard::display-name",
G_FILE_QUERY_INFO_NONE,
G_PRIORITY_DEFAULT,
button->update_button_cancellable,
update_label_get_info_cb,
g_object_ref (button));
}
@ -2286,8 +2329,7 @@ update_label_and_image (GtkFileChooserButton *button)
out:
if (file)
g_object_unref (file);
g_clear_object (&file);
if (label_text)
{
@ -2309,9 +2351,179 @@ out:
* Child Object Callbacks *
* ************************ */
/* File System */
static gboolean
mount_referenced_by_volume_activation_root (GList *volumes, GMount *mount)
{
GList *l;
GFile *mount_root;
gboolean ret;
ret = FALSE;
mount_root = g_mount_get_root (mount);
for (l = volumes; l != NULL; l = l->next)
{
GVolume *volume = G_VOLUME (l->data);
GFile *volume_activation_root;
volume_activation_root = g_volume_get_activation_root (volume);
if (volume_activation_root != NULL)
{
if (g_file_has_prefix (volume_activation_root, mount_root))
{
ret = TRUE;
g_object_unref (volume_activation_root);
break;
}
g_object_unref (volume_activation_root);
}
}
g_object_unref (mount_root);
return ret;
}
static GSList *
get_volumes_list (GVolumeMonitor *volume_monitor)
{
GSList *result;
GList *l, *ll;
GList *drives;
GList *volumes;
GList *mounts;
GDrive *drive;
GVolume *volume;
GMount *mount;
result = NULL;
/* first go through all connected drives */
drives = g_volume_monitor_get_connected_drives (volume_monitor);
for (l = drives; l != NULL; l = l->next)
{
drive = l->data;
volumes = g_drive_get_volumes (drive);
if (volumes)
{
for (ll = volumes; ll != NULL; ll = ll->next)
{
volume = ll->data;
mount = g_volume_get_mount (volume);
if (mount)
{
/* Show mounted volume */
result = g_slist_prepend (result, g_object_ref (mount));
g_object_unref (mount);
}
else
{
/* Do show the unmounted volumes in the sidebar;
* this is so the user can mount it (in case automounting
* is off).
*
* Also, even if automounting is enabled, this gives a visual
* cue that the user should remember to yank out the media if
* he just unmounted it.
*/
result = g_slist_prepend (result, g_object_ref (volume));
}
g_object_unref (volume);
}
g_list_free (volumes);
}
else if (g_drive_is_media_removable (drive) && !g_drive_is_media_check_automatic (drive))
{
/* If the drive has no mountable volumes and we cannot detect media change.. we
* display the drive in the sidebar so the user can manually poll the drive by
* right clicking and selecting "Rescan..."
*
* This is mainly for drives like floppies where media detection doesn't
* work.. but it's also for human beings who like to turn off media detection
* in the OS to save battery juice.
*/
result = g_slist_prepend (result, g_object_ref (drive));
}
g_object_unref (drive);
}
g_list_free (drives);
/* add all volumes that is not associated with a drive */
volumes = g_volume_monitor_get_volumes (volume_monitor);
for (l = volumes; l != NULL; l = l->next)
{
volume = l->data;
drive = g_volume_get_drive (volume);
if (drive)
{
g_object_unref (drive);
continue;
}
mount = g_volume_get_mount (volume);
if (mount)
{
/* show this mount */
result = g_slist_prepend (result, g_object_ref (mount));
g_object_unref (mount);
}
else
{
/* see comment above in why we add an icon for a volume */
result = g_slist_prepend (result, g_object_ref (volume));
}
g_object_unref (volume);
}
/* add mounts that has no volume (/etc/mtab mounts, ftp, sftp,...) */
mounts = g_volume_monitor_get_mounts (volume_monitor);
for (l = mounts; l != NULL; l = l->next)
{
mount = l->data;
volume = g_mount_get_volume (mount);
if (volume)
{
g_object_unref (volume);
continue;
}
/* if there's exists one or more volumes with an activation root
* inside the mount, don't display the mount
*/
if (mount_referenced_by_volume_activation_root (volumes, mount))
{
g_object_unref (mount);
continue;
}
/* show this mount */
result = g_slist_prepend (result, g_object_ref (mount));
g_object_unref (mount);
}
g_list_free (volumes);
g_list_free (mounts);
return result;
}
static void
fs_volumes_changed_cb (GtkFileSystem *fs,
volumes_changed (GVolumeMonitor *volume_monitor,
gpointer volume,
gpointer user_data)
{
GtkFileChooserButton *button = GTK_FILE_CHOOSER_BUTTON (user_data);
@ -2323,9 +2535,9 @@ fs_volumes_changed_cb (GtkFileSystem *fs,
button->n_volumes = 0;
volumes = _gtk_file_system_list_volumes (fs);
volumes = get_volumes_list (volume_monitor);
model_add_volumes (user_data, volumes);
g_slist_free (volumes);
g_slist_free_full (volumes, g_object_unref);
gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (button->filter_model));
@ -2474,16 +2686,11 @@ combo_box_changed_cb (GtkComboBox *combo_box,
break;
case ROW_TYPE_VOLUME:
{
GFile *base_file;
base_file = _gtk_file_system_volume_get_root (data);
if (base_file)
{
GFile *base_file = g_file_new_for_uri ("file:///");
gtk_file_chooser_button_select_file (GTK_FILE_CHOOSER (button), base_file, NULL);
file_was_set = TRUE;
g_object_unref (base_file);
}
}
break;
case ROW_TYPE_OTHER:
open_dialog (user_data);