summaryrefslogtreecommitdiff
path: root/baobab/src/baobab-utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'baobab/src/baobab-utils.c')
-rw-r--r--baobab/src/baobab-utils.c567
1 files changed, 567 insertions, 0 deletions
diff --git a/baobab/src/baobab-utils.c b/baobab/src/baobab-utils.c
new file mode 100644
index 00000000..12fbcbfb
--- /dev/null
+++ b/baobab/src/baobab-utils.c
@@ -0,0 +1,567 @@
+/*
+ * baobab-utils.c
+ * This file is part of baobab
+ *
+ * Copyright (C) 2005-2006 Fabio Marzocca <[email protected]>
+ *
+ * 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
+ */
+
+#include <config.h>
+
+#include <glib.h>
+#include <glib/gstdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <glib/gi18n.h>
+#include <glib/gprintf.h>
+#include <gtk/gtk.h>
+#include <gio/gio.h>
+#include <glibtop/mountlist.h>
+#include <glibtop/fsusage.h>
+
+#include "baobab.h"
+#include "baobab-treeview.h"
+#include "baobab-utils.h"
+#include "callbacks.h"
+
+void
+baobab_get_filesystem (BaobabFS *fs)
+{
+ size_t i;
+ glibtop_mountlist mountlist;
+ glibtop_mountentry *mountentries;
+
+ memset (fs, 0, sizeof *fs);
+
+ mountentries = glibtop_get_mountlist (&mountlist, FALSE);
+
+ for (i = 0; i < mountlist.number; ++i) {
+ GFile *file;
+ glibtop_fsusage fsusage;
+
+ file = g_file_new_for_path (mountentries[i].mountdir);
+
+ if (!baobab_is_excluded_location (file)) {
+
+ glibtop_get_fsusage (&fsusage, mountentries[i].mountdir);
+
+ fs->total += fsusage.blocks * fsusage.block_size;
+ fs->avail += fsusage.bfree * fsusage.block_size;
+ fs->used += (fsusage.blocks - fsusage.bfree) * fsusage.block_size;
+ }
+
+ g_object_unref (file);
+ }
+
+ g_free (mountentries);
+}
+
+void
+filechooser_cb (GtkWidget *chooser,
+ gint response,
+ gpointer data)
+{
+ if (response == GTK_RESPONSE_OK) {
+ gchar *filename;
+ GFile *file;
+
+ filename = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (chooser));
+ gtk_widget_hide (chooser);
+
+ file = g_file_new_for_uri (filename);
+ baobab_scan_location (file);
+ g_free (filename);
+ g_object_unref (file);
+ }
+ else {
+ gtk_widget_hide (chooser);
+ }
+}
+
+/*
+ * GtkFileChooser to select a directory to scan
+ */
+gchar *
+dir_select (gboolean SEARCH, GtkWidget *parent)
+{
+ static GtkWidget *file_chooser = NULL;
+ GtkWidget *toggle;
+
+ if (file_chooser == NULL) {
+ file_chooser = gtk_file_chooser_dialog_new (_("Select Folder"),
+ GTK_WINDOW (parent),
+ GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
+ GTK_STOCK_CANCEL,
+ GTK_RESPONSE_CANCEL,
+ GTK_STOCK_OPEN,
+ GTK_RESPONSE_OK, NULL);
+
+ gtk_file_chooser_set_show_hidden (GTK_FILE_CHOOSER (file_chooser), FALSE);
+ gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (file_chooser),
+ g_get_home_dir ());
+ /* add extra widget */
+ toggle = gtk_check_button_new_with_mnemonic (_("_Show hidden folders"));
+ gtk_widget_show (toggle);
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), FALSE);
+ g_signal_connect ((gpointer) toggle, "toggled",
+ G_CALLBACK (on_toggled), file_chooser);
+ gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER (file_chooser),
+ toggle);
+
+ g_signal_connect (file_chooser, "response",
+ G_CALLBACK (filechooser_cb), NULL);
+ g_signal_connect (file_chooser, "destroy",
+ G_CALLBACK (gtk_widget_destroyed), &file_chooser);
+
+ gtk_window_set_modal (GTK_WINDOW (file_chooser), TRUE);
+ gtk_window_set_position (GTK_WINDOW (file_chooser), GTK_WIN_POS_CENTER_ON_PARENT);
+ }
+
+ gtk_widget_show (GTK_WIDGET (file_chooser));
+
+ return NULL;
+}
+
+void
+on_toggled (GtkToggleButton *togglebutton, gpointer dialog)
+{
+ gtk_file_chooser_set_show_hidden (GTK_FILE_CHOOSER (dialog),
+ !gtk_file_chooser_get_show_hidden
+ (GTK_FILE_CHOOSER (dialog)));
+}
+
+void
+set_ui_action_sens (const gchar *name, gboolean sens)
+{
+ GtkAction *a;
+
+ a = GTK_ACTION (gtk_builder_get_object (baobab.main_ui, name));
+ gtk_action_set_sensitive (a, sens);
+}
+
+void
+set_ui_widget_sens (const gchar *name, gboolean sens)
+{
+ GtkWidget *w;
+
+ w = GTK_WIDGET (gtk_builder_get_object (baobab.main_ui, name));
+ gtk_widget_set_sensitive (w, sens);
+}
+
+gboolean
+show_bars (GtkTreeModel *mdl,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ gpointer data)
+{
+ GtkTreeIter parent;
+ gdouble perc;
+ gint readelements, size_col;
+ guint64 refsize, size;
+ char *sizecstr = NULL;
+
+ if (baobab.show_allocated)
+ size_col = (gint) COL_H_ALLOCSIZE;
+ else
+ size_col = (gint) COL_H_SIZE;
+
+ if (gtk_tree_model_iter_parent (mdl, &parent, iter)) {
+ gtk_tree_model_get (mdl, iter, COL_H_ELEMENTS,
+ &readelements, -1);
+
+ if (readelements == -1) {
+ gtk_tree_store_set (GTK_TREE_STORE (mdl), iter,
+ COL_DIR_SIZE, "--",
+ COL_ELEMENTS, "--", -1);
+ return FALSE;
+ }
+
+ gtk_tree_model_get (mdl, &parent, COL_H_ELEMENTS,
+ &readelements, -1);
+
+ gtk_tree_model_get (mdl, iter, size_col, &size, -1);
+ sizecstr = g_format_size_for_display (size);
+
+ if (readelements == -1) {
+ gtk_tree_store_set (GTK_TREE_STORE (mdl), iter,
+ COL_DIR_SIZE, sizecstr, -1);
+
+ g_free (sizecstr);
+ return FALSE;
+ }
+
+ gtk_tree_model_get (mdl, &parent, size_col, &refsize, -1);
+ perc = (refsize != 0) ? ((gdouble) size * 100) / (gdouble) refsize : 0.0;
+
+ gtk_tree_store_set (GTK_TREE_STORE (mdl), iter,
+ COL_DIR_SIZE, sizecstr,
+ COL_H_PERC, perc, -1);
+
+ g_free (sizecstr);
+ } else {
+ gtk_tree_model_get (mdl, iter, COL_H_ELEMENTS,
+ &readelements, -1);
+
+ if (readelements != -1) {
+ gtk_tree_model_get (mdl, iter, size_col, &size,
+ -1);
+ sizecstr = g_format_size_for_display (size);
+
+ gtk_tree_store_set (GTK_TREE_STORE (mdl), iter,
+ COL_H_PERC, 100.0,
+ COL_DIR_SIZE, sizecstr, -1);
+
+ g_free (sizecstr);
+ }
+ else {
+ gtk_tree_store_set (GTK_TREE_STORE (mdl), iter,
+ COL_DIR_SIZE, "--",
+ COL_ELEMENTS, "--", -1);
+ }
+ }
+
+ return FALSE;
+}
+
+void
+message (const gchar *primary_msg,
+ const gchar *secondary_msg,
+ GtkMessageType type,
+ GtkWidget *parent)
+{
+ GtkWidget *dialog;
+ dialog = gtk_message_dialog_new (GTK_WINDOW (parent),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ type,
+ GTK_BUTTONS_OK, "%s", primary_msg);
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+ "%s", secondary_msg);
+ gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+}
+
+gint
+messageyesno (const gchar *primary_msg,
+ const gchar *secondary_msg,
+ GtkMessageType type,
+ gchar *ok_button,
+ GtkWidget *parent)
+{
+ GtkWidget *dialog;
+ GtkWidget *button;
+ gint response;
+
+ dialog = gtk_message_dialog_new (GTK_WINDOW (parent),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ type,
+ GTK_BUTTONS_CANCEL,
+ "%s", primary_msg);
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+ "%s", secondary_msg);
+
+ button = gtk_button_new_with_mnemonic (ok_button);
+ gtk_widget_set_can_default (button, TRUE);
+ gtk_widget_show (button);
+
+ gtk_dialog_add_action_widget (GTK_DIALOG (dialog), button, GTK_RESPONSE_OK);
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
+ response = gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+
+ return response;
+}
+
+gboolean
+baobab_check_dir (GFile *file)
+{
+ GFileInfo *info;
+ GError *error = NULL;
+ gboolean ret = TRUE;
+
+ if (baobab_is_excluded_location (file)) {
+ message("", _("Cannot check an excluded folder!"), GTK_MESSAGE_INFO, baobab.window);
+ return FALSE;
+ }
+
+ info = g_file_query_info (file,
+ G_FILE_ATTRIBUTE_STANDARD_TYPE,
+ G_FILE_QUERY_INFO_NONE,
+ NULL,
+ &error);
+
+ if (!info) {
+ message("", error->message, GTK_MESSAGE_INFO, baobab.window);
+ g_error_free (error);
+
+ return FALSE;
+ }
+
+ if ((g_file_info_get_file_type (info) != G_FILE_TYPE_DIRECTORY) ||
+ is_virtual_filesystem(file)) {
+
+ char *error_msg = NULL;
+ gchar *name = NULL;
+
+ name = g_file_get_parse_name (file);
+ error_msg = g_strdup_printf (_("\"%s\" is not a valid folder"),
+ name);
+
+ message (error_msg, _("Could not analyze disk usage."),
+ GTK_MESSAGE_ERROR, baobab.window);
+
+ g_free (error_msg);
+ g_free (name);
+ ret = FALSE;
+ }
+
+ g_object_unref(info);
+
+ return ret;
+}
+
+static void
+add_popupmenu_item (GtkMenu *pmenu, const gchar *label, const gchar *stock, GCallback item_cb)
+{
+ GtkWidget *item;
+ GtkWidget *image;
+
+ item = gtk_image_menu_item_new_with_mnemonic (label);
+ image = gtk_image_new_from_stock (stock, GTK_ICON_SIZE_MENU);
+ gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
+
+ g_signal_connect (item, "activate", item_cb, NULL);
+
+ gtk_container_add (GTK_CONTAINER (pmenu), item);
+}
+
+void
+popupmenu_list (GtkTreePath *path, GdkEventButton *event, gboolean can_trash)
+{
+ GtkWidget *pmenu;
+ gchar *path_to_string;
+
+ /* path_to_string is freed in callback function */
+ path_to_string = gtk_tree_path_to_string (path);
+
+ pmenu = gtk_menu_new ();
+
+ add_popupmenu_item (GTK_MENU (pmenu),
+ _("_Open Folder"),
+ "gtk-open",
+ G_CALLBACK (open_file_cb));
+
+ if (baobab.is_local && can_trash) {
+ add_popupmenu_item (GTK_MENU (pmenu),
+ _("Mo_ve to Trash"),
+ "gtk-delete",
+ G_CALLBACK (trash_dir_cb));
+ }
+
+ gtk_widget_show_all (pmenu);
+ gtk_menu_popup (GTK_MENU (pmenu), NULL, NULL, NULL, NULL,
+ event->button, event->time);
+}
+
+void
+open_file_with_application (GFile *file)
+{
+ GAppInfo *application;
+ gchar *primary;
+ GFileInfo *info;
+ gchar *uri_scheme;
+ const char *content;
+ gboolean local = FALSE;
+
+ info = g_file_query_info (file,
+ G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
+ G_FILE_QUERY_INFO_NONE,
+ NULL,
+ NULL);
+ if (!info) return;
+
+ uri_scheme = g_file_get_uri_scheme (file);
+ if (g_ascii_strcasecmp(uri_scheme,"file") == 0) local = TRUE;
+
+ content = g_file_info_get_content_type (info);
+ application = g_app_info_get_default_for_type (content, TRUE);
+
+ if (!application) {
+ primary = g_strdup_printf (_("Could not open folder \"%s\""),
+ g_file_get_basename (file));
+ message (primary,
+ _("There is no installed viewer capable "
+ "of displaying the folder."),
+ GTK_MESSAGE_ERROR,
+ baobab.window);
+ g_free (primary);
+ }
+ else {
+ GList *uris = NULL;
+ gchar *uri;
+
+ uri = g_file_get_uri (file);
+ uris = g_list_append (uris, uri);
+ g_app_info_launch_uris (application, uris, NULL, NULL);
+
+ g_list_free (uris);
+ g_free (uri);
+ }
+
+ g_free (uri_scheme);
+
+ if (application)
+ g_object_unref (application);
+
+ g_object_unref (info);
+}
+
+gboolean
+can_trash_file (GFile *file)
+{
+ GFileInfo *info;
+ gboolean can_trash = FALSE;
+
+ info = g_file_query_info (file,
+ G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH,
+ G_FILE_QUERY_INFO_NONE,
+ NULL,
+ NULL);
+
+ if (info) {
+ if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH)) {
+ can_trash = g_file_info_get_attribute_boolean (info,
+ G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH);
+ }
+
+ g_object_unref (info);
+ }
+
+ return can_trash;
+}
+
+gboolean
+trash_file (GFile *file)
+{
+ GError *error = NULL;
+
+ if (!g_file_trash (file, NULL, &error)) {
+ GFileInfo *info;
+ char *str = NULL;
+ char *mess;
+
+ info = g_file_query_info (file,
+ G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME,
+ G_FILE_QUERY_INFO_NONE,
+ NULL,
+ NULL);
+
+ if (info) {
+ const char *displayname = g_file_info_get_display_name (info);
+ if (displayname)
+ str = g_strdup_printf (_("Could not move \"%s\" to the Trash"),
+ displayname);
+
+ g_object_unref (info);
+ }
+
+ /* fallback */
+ if (str == NULL)
+ str = g_strdup (_("Could not move file to the Trash"));
+
+ mess = g_strdup_printf (_("Details: %s"), error->message);
+ message (str, mess, GTK_MESSAGE_ERROR, baobab.window);
+ g_free (str);
+ g_free (mess);
+ g_error_free (error);
+
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+gchar *
+baobab_mateconf_get_string_with_default (MateConfClient *client,
+ const gchar *key,
+ const gchar *def)
+{
+ gchar *val;
+
+ val = mateconf_client_get_string (client, key, NULL);
+ return val ? val : g_strdup (def);
+}
+
+gboolean
+baobab_help_display (GtkWindow *parent,
+ const gchar *file_name,
+ const gchar *link_id)
+{
+ GError *error = NULL;
+ char *uri;
+ gboolean ret;
+
+ uri = (link_id) ?
+ g_strdup_printf ("ghelp:%s#%s", file_name, link_id) :
+ g_strdup_printf ("ghelp:%s", file_name);
+
+ ret = gtk_show_uri (gtk_window_get_screen (parent),
+ uri, gtk_get_current_event_time (), &error);
+ g_free (uri);
+
+ if (error != NULL) {
+ GtkWidget *dialog;
+
+ dialog = gtk_message_dialog_new (parent,
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_CLOSE,
+ _("There was an error displaying help."));
+
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+ "%s", error->message);
+
+ g_signal_connect (G_OBJECT (dialog), "response",
+ G_CALLBACK (gtk_widget_destroy), NULL);
+
+ gtk_widget_show (dialog);
+
+ g_error_free (error);
+ }
+
+ return ret;
+}
+
+gboolean
+is_virtual_filesystem (GFile *file)
+{
+ gboolean ret = FALSE;
+ char *path;
+
+ path = g_file_get_path (file);
+
+ /* FIXME: we need a better way to check virtual FS */
+ if (path != NULL) {
+ if ((strcmp (path, "/proc") == 0) ||
+ (strcmp (path, "/sys") == 0))
+ ret = TRUE;
+ }
+
+ g_free (path);
+
+ return ret;
+}