/* * gdu-utils.c * * Copyright (C) 2008-2009 Red Hat, Inc. * * This library 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 library 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 * Library General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * Author: Tomas Bzatek * */ #ifdef HAVE_CONFIG_H #include /* for GETTEXT_PACKAGE */ #endif #include #include #include #include #include static GduPresentable * _find_presentable (char *mount_path, char *device_path) { GduPool *pool; GList *presentables, *presentables_w; GduPresentable *presentable = NULL; GduPresentable *pres_w; GduDevice *device; const char *device_mount; const char *device_file; GFile *file1, *file2; pool = gdu_pool_new (); presentables = gdu_pool_get_presentables (pool); presentables_w = presentables; while (presentables_w != NULL) { pres_w = presentables_w->data; #if 0 if (pres_w) g_print ("presentable '%s', ref count = %d [%p]\n", gdu_presentable_get_name (pres_w), ((GObject*)pres_w)->ref_count, pres_w); #endif if (! presentable && pres_w) { device = gdu_presentable_get_device (pres_w); if (device) { device_mount = gdu_device_get_mount_path (device); device_file = gdu_device_get_device_file (device); /* match mount_path */ if (mount_path && device_mount && strlen (device_mount) > 1) { /* compare via GFile routines */ file1 = g_file_new_for_commandline_arg (mount_path); file2 = g_file_new_for_path (device_mount); if (g_file_equal (file1, file2)) presentable = g_object_ref (pres_w); g_object_unref (file1); g_object_unref (file2); if (presentable) break; } /* match device_path */ if (device_path && device_file && strlen (device_file) > 1) { if (strcmp (device_file, device_path) == 0) { presentable = g_object_ref (pres_w); break; } } g_object_unref (device); } } presentables_w = g_list_next (presentables_w); } g_list_foreach (presentables, (GFunc) g_object_unref, NULL); g_list_free (presentables); g_object_unref (pool); return presentable; } GduPresentable * find_presentable_from_mount_path (char *mount_path) { g_return_val_if_fail (mount_path != NULL, NULL); g_return_val_if_fail (strlen (mount_path) > 1, NULL); return _find_presentable (mount_path, NULL); } GduPresentable * find_presentable_from_device_path (char *device_path) { g_return_val_if_fail (device_path != NULL, NULL); g_return_val_if_fail (strlen (device_path) > 1, NULL); return _find_presentable (NULL, device_path); } /* ---------------------------------------------------------------------------------------------------- */ /* Volume selector widget */ static void gdu_util_presentable_combo_box_add_item (GtkListStore *store, GduPresentable *presentable) { char *name = NULL; char *display_name = NULL; GdkPixbuf *pixbuf = NULL; GtkTreeIter iter; GduDevice *device = NULL; GduPresentable *toplevel_presentable = NULL; GduDevice *toplevel_device = NULL; device = gdu_presentable_get_device (presentable); toplevel_presentable = gdu_presentable_get_toplevel (presentable); if (toplevel_presentable) toplevel_device = gdu_presentable_get_device (toplevel_presentable); /* Make display name */ if (device) { name = g_strdup (gdu_device_id_get_label (device)); if (name && strlen (name) > 0) display_name = g_strdup (name); g_free (name); name = NULL; } if (! display_name) { name = gdu_presentable_get_name (presentable); if (name && strlen (name) > 0) display_name = g_strdup_printf ("(%s)", name); g_free (name); name = NULL; } if (! display_name && device) display_name = g_strdup_printf ("(%s)", gdu_device_get_device_file (device)); /* Get an icon */ pixbuf = gdu_util_get_pixbuf_for_presentable (presentable, GTK_ICON_SIZE_DIALOG); if (device || toplevel_device) { gtk_list_store_append (store, &iter); /* gtk_list_store_set() refs objects itself */ gtk_list_store_set (store, &iter, 0, presentable, 1, display_name, 2, device ? gdu_device_get_device_file (device) : gdu_device_get_device_file (toplevel_device), 3, pixbuf, -1); } g_free (display_name); if (device) g_object_unref (device); if (toplevel_presentable) g_object_unref (toplevel_presentable); if (toplevel_device) g_object_unref (toplevel_device); g_free (name); if (pixbuf) g_object_unref (pixbuf); } static GtkListStore * gdu_util_presentable_combo_box_create_store (GduPool *pool) { GList *l; GtkListStore *store; GList *presentables = NULL; GtkTreeIter iter; store = gtk_list_store_new (4, G_TYPE_OBJECT, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_OBJECT); gtk_list_store_append (store, &iter); gtk_list_store_set (store, &iter, 0, NULL, 1, NULL, 2, NULL, 3, NULL, -1); if (pool != NULL) presentables = gdu_pool_get_presentables (pool); for (l = presentables; l != NULL; l = l->next) { GduPresentable *presentable = l->data; GduPresentable *toplevel_presentable; GduDevice *toplevel_device = NULL; GduDevice *device; GList *enclosed_presentables = NULL; device = gdu_presentable_get_device (presentable); toplevel_presentable = gdu_presentable_get_toplevel (presentable); if (toplevel_presentable) toplevel_device = gdu_presentable_get_device (toplevel_presentable); /* First eliminate all non-toplevel presentables */ if (toplevel_device != NULL && toplevel_presentable == presentable && gdu_device_is_removable (toplevel_device)) { /* determine parent presentables (in case of toplevel drive) */ enclosed_presentables = gdu_pool_get_enclosed_presentables (pool, presentable); g_print ("presentable %s [%s], enclosed_presentables = %d, toplevel_presentable = %p vs. %p, gdu_device_is_partition_table = %d, gdu_device_is_optical_disc = %d, gdu_device_drive_get_media = '%s'\n", gdu_presentable_get_name (presentable), device ? gdu_device_get_device_file (device) : "no device.", g_list_length (enclosed_presentables), toplevel_presentable, presentable, gdu_device_is_partition_table (device), gdu_device_is_optical_disc (device), gdu_device_drive_get_media (device)); GList *enclosed_presentables_l; for (enclosed_presentables_l = enclosed_presentables; enclosed_presentables_l != NULL; enclosed_presentables_l = enclosed_presentables_l->next) { GduPresentable *presentable_e = enclosed_presentables_l->data; GduDevice *device_e = gdu_presentable_get_device (presentable_e); g_print (" +--- %s, GDU_IS_DRIVE = %d, GDU_IS_VOLUME = %d, GDU_IS_VOLUME_HOLE = %d, device = %p [%s]\n", gdu_presentable_get_name (presentable_e), GDU_IS_DRIVE (presentable_e), GDU_IS_VOLUME (presentable_e), GDU_IS_VOLUME_HOLE (presentable_e), device_e, device_e ? gdu_device_get_device_file (device_e) : "no device."); gdu_util_presentable_combo_box_add_item (store, presentable_e); if (device_e) g_object_unref (device_e); } g_list_foreach (enclosed_presentables, (GFunc) g_object_unref, NULL); g_list_free (enclosed_presentables); } if (toplevel_presentable) g_object_unref (toplevel_presentable); if (device) g_object_unref (device); if (toplevel_device) g_object_unref (toplevel_device); } g_list_foreach (presentables, (GFunc) g_object_unref, NULL); g_list_free (presentables); return store; } static void gdu_util_presentable_combo_box_text_renderer_func (GtkCellLayout *cell_layout, GtkCellRenderer *cell, GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer user_data) { gchar *name = NULL; gchar *device_path = NULL; gchar *display_name; gboolean popup_shown = FALSE; GtkTreePath *path; GtkTreeIter active_iter; gint *indices; gboolean sensitive; gboolean visible; GduPresentable *presentable; gtk_tree_model_get (tree_model, iter, 1, &name, 2, &device_path, -1); g_object_get (G_OBJECT (user_data), "popup-shown", &popup_shown, NULL); path = gtk_tree_model_get_path (tree_model, iter); indices = gtk_tree_path_get_indices (path); visible = TRUE; if (indices[0] == 0) { sensitive = FALSE; display_name = g_strdup (_("Select a volume...")); if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (user_data), &active_iter)) { presentable = NULL; gtk_tree_model_get (tree_model, &active_iter, 0, &presentable, -1); if (presentable) { visible = FALSE; g_object_unref (presentable); } } } else { sensitive = TRUE; if (popup_shown) display_name = g_strdup_printf (" %s\n %s", name, device_path); else display_name = g_strdup_printf (" %s", name); } g_object_set (cell, "sensitive", sensitive, NULL); if (GTK_IS_CELL_RENDERER_TEXT (cell)) g_object_set (cell, "markup", display_name, NULL); g_free (display_name); g_free (name); g_free (device_path); gtk_tree_path_free (path); } GtkWidget * gdu_util_presentable_combo_box_create (GduPool *pool) { GtkListStore *store; GtkCellRenderer *renderer; GtkWidget *combo_box; combo_box = gtk_combo_box_new (); store = gdu_util_presentable_combo_box_create_store (pool); gtk_combo_box_set_model (GTK_COMBO_BOX (combo_box), GTK_TREE_MODEL (store)); g_object_unref (store); renderer = gtk_cell_renderer_pixbuf_new (); gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo_box), renderer, FALSE); gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo_box), renderer, "pixbuf", 3, NULL); gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (combo_box), renderer, gdu_util_presentable_combo_box_text_renderer_func, combo_box, NULL); renderer = gtk_cell_renderer_text_new (); gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo_box), renderer, TRUE); gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (combo_box), renderer, gdu_util_presentable_combo_box_text_renderer_func, combo_box, NULL); gtk_combo_box_set_active (GTK_COMBO_BOX (combo_box), 0); return combo_box; } gboolean gdu_util_presentable_combo_box_select (GtkWidget *combo_box, GduPresentable *presentable) { GtkTreeModel *model; GtkTreeIter iter; gboolean ret; ret = FALSE; model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo_box)); gtk_tree_model_get_iter_first (model, &iter); do { GduPresentable *iter_presentable; gtk_tree_model_get (model, &iter, 0, &iter_presentable, -1); if (iter_presentable != NULL && iter_presentable == presentable) { gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combo_box), &iter); ret = TRUE; } if (iter_presentable) g_object_unref (iter_presentable); } while (!ret && gtk_tree_model_iter_next (model, &iter)); if (! ret) gtk_combo_box_set_active (GTK_COMBO_BOX (combo_box), 0); return ret; } GduPresentable * gdu_util_presentable_combo_box_get_selected (GtkWidget *combo_box) { GtkTreeModel *model; GtkTreeIter iter; GduPresentable *presentable; model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo_box)); presentable = NULL; if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (combo_box), &iter)) gtk_tree_model_get (model, &iter, 0, &presentable, -1); return presentable; } void gdu_util_presentable_combo_box_rebuild (GtkWidget *combo_box, GduPool *pool) { GtkListStore *store; GduPresentable *old_presentable; old_presentable = gdu_util_presentable_combo_box_get_selected (combo_box); store = gdu_util_presentable_combo_box_create_store (pool); gtk_combo_box_set_model (GTK_COMBO_BOX (combo_box), GTK_TREE_MODEL (store)); g_object_unref (store); gdu_util_presentable_combo_box_select (combo_box, old_presentable); if (old_presentable) g_object_unref (old_presentable); }