/* PureAdmin
* Copyright (C) 2003 Isak Savo
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*
* Dirbrowser-widget (similar to the file-selector distributet with GTK+). This is
* in fact a stand-alone widget that easily can be used in other projects. Please give
* me credit for it and leave the copyright-notice is untouched. Thx!
*
* Simply add dirbrowser.c and .h to you project and use the functions declared in the .h-file
* to access the widget!
*
* Copyright (C) 2003 Isak Savo
*/
/* FIXME: the text in the entry is the one that is used. We need a nicer handling!
* Proposal: add a property, called 'directory' or similar a'la fileselector! */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <gtk/gtk.h>
#include "dirbrowser.h"
/* These should not be included if used in other projects */
#include "globals.h"
#include "helper.h"
#ifndef MAXPATHLEN
# ifdef PATH_MAX
# define MAXPATHLEN PATH_MAX
# else
# define MAXPATHLEN 2048
# endif /* PATH:MAX */
#endif /* MAXPATHLEN */
static GtkWindowClass *parent_class = NULL;
/* Internal functions */
gboolean dirbrowser_select (Dirbrowser *dbr, const gchar *directory);
/*gboolean dirbrowser_populate (Dirbrowser *dbr, const gchar *directory);*/
void dirbrowser_populate_full_dir (Dirbrowser *dbr, const char *directory);
gint dirbrowser_populate_children (Dirbrowser *dbr, GtkTreeIter parent_iter, const char *directory);
static void dirbrowser_class_init (DirbrowserClass *klass);
static void dirbrowser_init (Dirbrowser *dbr);
static void dirbrowser_finalize (GObject *object);
static void dirbrowser_destroy (GtkObject *object);
static void dirbrowser_map (GtkWidget *widget);
void dirbrowser_cursor_changed (GtkTreeView *treeview, gpointer user_data);
gboolean dirbrowser_btnpress_event (GtkTreeView *treeview, GdkEventButton *event, gpointer user_data);
void dirbrowser_entry_changed (GtkEditable *entry, gpointer data);
void dirbrowser_btnhome_clicked (GtkButton *btn, gpointer data);
gchar **_dirbrowser_directory_split (const gchar *directory);
gchar *_dirbrowser_treepath_to_fspath (const GtkTreePath *c_path, GtkTreeModel *model);
GList *_dirbrowser_get_dircontents (const gchar *directory);
static void dirbrowser_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec);
static void dirbrowser_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec);
enum {
COL_IMAGE = 0,
COL_NAME,
COL_FSNAME,
N_DIR_COLUMNS
};
enum {
PROP_0,
PROP_DIRECTORY
};
static gboolean grab_default (GtkWidget *widget)
{
gtk_widget_grab_default (widget);
return FALSE;
}
GType
dirbrowser_get_type (void)
{
static GType dirbrowser_type = 0;
if (!dirbrowser_type)
{
static const GTypeInfo dirbrowser_info =
{
sizeof (DirbrowserClass),
NULL, /* base_init */
NULL, /* base_finalize */
(GClassInitFunc) dirbrowser_class_init,
NULL, /* class_finalize */
NULL, /* class_data */
sizeof (Dirbrowser),
0, /* n_preallocs */
(GInstanceInitFunc) dirbrowser_init,
};
dirbrowser_type =
g_type_register_static (GTK_TYPE_DIALOG, "Dirbrowser",
&dirbrowser_info, 0);
}
return dirbrowser_type;
}
static void
dirbrowser_class_init (DirbrowserClass *klass)
{
GObjectClass *gobject_class;
GtkObjectClass *object_class;
GtkWidgetClass *widget_class;
gobject_class = (GObjectClass*) klass;
object_class = (GtkObjectClass*) klass;
widget_class = (GtkWidgetClass*) klass;
parent_class = g_type_class_peek_parent (klass);
gobject_class->finalize = dirbrowser_finalize;
object_class->destroy = dirbrowser_destroy;
widget_class->map = dirbrowser_map;
gobject_class->set_property = dirbrowser_set_property;
gobject_class->get_property = dirbrowser_get_property;
g_object_class_install_property (gobject_class,
PROP_DIRECTORY,
g_param_spec_string ("directory",
N_("Directory"),
N_("The currently selected directory"),
NULL,
G_PARAM_READABLE | G_PARAM_WRITABLE));
}
static void dirbrowser_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
Dirbrowser *db;
db = DIRBROWSER (object);
switch (prop_id)
{
case PROP_DIRECTORY:
dirbrowser_set_directory (db, g_value_get_string (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void dirbrowser_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
Dirbrowser *db;
db = DIRBROWSER (object);
switch (prop_id)
{
case PROP_DIRECTORY:
g_value_set_string (value,
dirbrowser_get_directory (db));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
dirbrowser_init (Dirbrowser *dbr)
{
GtkDialog *dlg;
GtkTreeStore *store;
GtkTreeViewColumn *column;
GtkTreeIter iter;
GtkCellRenderer *renderer_img, *renderer_txt;
GtkWidget *vbox;
dlg = GTK_DIALOG (dbr);
gtk_widget_set_size_request (GTK_WIDGET (dlg), 250, 350);
gtk_container_set_border_width (GTK_CONTAINER (dlg), 6);
gtk_window_set_title (GTK_WINDOW (dlg), _("Select directory"));
gtk_dialog_set_has_separator (GTK_DIALOG (dlg), FALSE);
vbox = GTK_DIALOG (dlg)->vbox;
gtk_widget_show (vbox);
dbr->main_vbox = gtk_vbox_new (FALSE, 6);
gtk_widget_show (dbr->main_vbox);
gtk_box_pack_start (GTK_BOX (vbox), dbr->main_vbox, TRUE, TRUE, 0);
gtk_container_set_border_width (GTK_CONTAINER (dbr->main_vbox), 6);
dbr->btnbox = gtk_hbutton_box_new ();
gtk_widget_show (dbr->btnbox);
gtk_box_pack_start (GTK_BOX (dbr->main_vbox), dbr->btnbox, FALSE, FALSE, 0);
gtk_button_box_set_layout (GTK_BUTTON_BOX (dbr->btnbox), GTK_BUTTONBOX_START);
dbr->btn_home = gtk_button_new_from_stock ("gtk-home");
gtk_widget_show (dbr->btn_home);
gtk_container_add (GTK_CONTAINER (dbr->btnbox), dbr->btn_home);
GTK_WIDGET_SET_FLAGS (dbr->btn_home, GTK_CAN_DEFAULT);
gtk_button_set_relief (GTK_BUTTON (dbr->btn_home), GTK_RELIEF_HALF);
dbr->location = gtk_entry_new ();
gtk_widget_show (dbr->location);
gtk_box_pack_start (GTK_BOX (dbr->main_vbox), dbr->location, FALSE, FALSE, 0);
dbr->scr_win = gtk_scrolled_window_new (NULL, NULL);
gtk_widget_show (dbr->scr_win);
gtk_box_pack_start (GTK_BOX (dbr->main_vbox), dbr->scr_win, TRUE, TRUE, 0);
dbr->dir_tree = gtk_tree_view_new ();
gtk_widget_show (dbr->dir_tree);
gtk_container_add (GTK_CONTAINER (dbr->scr_win), dbr->dir_tree);
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (dbr->dir_tree), TRUE);
gtk_widget_show (dlg->action_area);
gtk_button_box_set_layout (GTK_BUTTON_BOX (dlg->action_area), GTK_BUTTONBOX_END);
dbr->btn_cancel = gtk_button_new_from_stock ("gtk-cancel");
gtk_widget_show (dbr->btn_cancel);
gtk_dialog_add_action_widget (GTK_DIALOG (dlg), dbr->btn_cancel, GTK_RESPONSE_CANCEL);
GTK_WIDGET_SET_FLAGS (dbr->btn_cancel, GTK_CAN_DEFAULT);
dbr->btn_ok = gtk_button_new_from_stock ("gtk-ok");
gtk_widget_show (dbr->btn_ok);
gtk_dialog_add_action_widget (GTK_DIALOG (dlg), dbr->btn_ok, GTK_RESPONSE_OK);
GTK_WIDGET_SET_FLAGS (dbr->btn_ok, GTK_CAN_DEFAULT);
/* Initiate the treeview */
gtk_tree_selection_set_mode (gtk_tree_view_get_selection (GTK_TREE_VIEW (dbr->dir_tree)),
GTK_SELECTION_SINGLE);
store = gtk_tree_store_new (N_DIR_COLUMNS,
GDK_TYPE_PIXBUF,
G_TYPE_STRING,
G_TYPE_STRING);
gtk_tree_view_set_model (GTK_TREE_VIEW (dbr->dir_tree), GTK_TREE_MODEL (store));
g_object_unref (G_OBJECT (store));
column = gtk_tree_view_column_new ();
renderer_img = gtk_cell_renderer_pixbuf_new ();
renderer_txt = gtk_cell_renderer_text_new ();
/* Only create a view for the first two columns (icon and utf8 name), the
* last column is the *real* fsname, as got from g_dir_read_name()
*/
gtk_tree_view_column_pack_start (column, renderer_img, FALSE);
gtk_tree_view_column_add_attribute (column, renderer_img,
"pixbuf", COL_IMAGE);
gtk_tree_view_column_pack_end (column, renderer_txt, TRUE);
gtk_tree_view_column_add_attribute (column, renderer_txt,
"text", COL_NAME);
gtk_tree_view_insert_column (GTK_TREE_VIEW (dbr->dir_tree), column, -1);
/* Directory-icon -- Rendered using the current theme */
dbr->icon = gtk_widget_render_icon (GTK_WIDGET (dbr), GTK_STOCK_OPEN,
GTK_ICON_SIZE_MENU,
NULL);
/* Add root-directory w/ children */
gtk_tree_store_append (GTK_TREE_STORE (store), &iter, NULL);
gtk_tree_store_set (GTK_TREE_STORE (store), &iter,
COL_IMAGE, dbr->icon,
COL_NAME, "/",
COL_FSNAME, "/",
-1);
dirbrowser_populate_children (dbr, iter, "/");
dbr->hid_cursor_changed =
g_signal_connect ((gpointer) dbr->dir_tree, "cursor_changed",
G_CALLBACK (dirbrowser_cursor_changed),
(gpointer) dbr);
g_signal_connect ((gpointer) dbr->dir_tree, "button_press_event",
G_CALLBACK (dirbrowser_btnpress_event),
(gpointer) dbr);
dbr->hid_entry_changed =
g_signal_connect ((gpointer) dbr->location, "changed",
G_CALLBACK (dirbrowser_entry_changed),
(gpointer) dbr);
g_signal_connect_swapped (dbr->location, "focus_in_event",
G_CALLBACK (grab_default),
dbr->btn_ok);
g_signal_connect_swapped (dbr->location, "activate",
G_CALLBACK (gtk_button_clicked),
dbr->btn_ok);
g_signal_connect ((gpointer) dbr->btn_home, "clicked",
G_CALLBACK (dirbrowser_btnhome_clicked),
(gpointer) dbr);
gtk_widget_grab_focus (dbr->location);
}
/* FIXME: Are these needed?? */
static void dirbrowser_finalize (GObject *object)
{
G_OBJECT_CLASS (parent_class)->finalize (object);
}
static void dirbrowser_destroy (GtkObject *object)
{
GTK_OBJECT_CLASS (parent_class)->destroy (object);
}
static void dirbrowser_map (GtkWidget *widget)
{
GTK_WIDGET_CLASS (parent_class)->map (widget);
}
void dirbrowser_set_directory (Dirbrowser *dir_browser, const char *directory)
{
gchar *directory_utf8;
g_return_if_fail (IS_DIRBROWSER (dir_browser));
g_return_if_fail (directory != NULL);
g_return_if_fail (g_file_test (directory, G_FILE_TEST_IS_DIR));
directory_utf8 = g_filename_to_utf8 (directory, -1, NULL, NULL, NULL);
g_return_if_fail (directory_utf8 != NULL);
if (dir_browser->location)
gtk_entry_set_text (GTK_ENTRY (dir_browser->location), directory_utf8);
g_object_notify (G_OBJECT (dir_browser), "directory");
g_free (directory_utf8);
}
/**
* dirbrowser_get_directory:
* @dir_browser: a #Dirbrowser
*
* This functions returns the current selected directory in the current
* on-disk encoding. (see g_filename_from_utf8() in gtk-docs).
* The returned string points to a statically allocated buffer and
* should be copied if you plan to keep it around.
*
* If no directory is selected, the empty string, "", is returned.
*
* Return value: currently selected directory in the on-disk encoding.
**/
G_CONST_RETURN gchar *dirbrowser_get_directory (Dirbrowser *dir_browser)
{
static const gchar nothing[2] = "";
static gchar something[MAXPATHLEN+2];
const gchar *utf8_name;
gchar *sys_name;
g_return_val_if_fail (IS_DIRBROWSER (dir_browser), nothing);
if (dir_browser->location)
{
utf8_name = gtk_entry_get_text (GTK_ENTRY (dir_browser->location));
sys_name = g_filename_from_utf8 (utf8_name, -1, NULL, NULL, NULL);
if (!sys_name)
return nothing;
strncpy (something, sys_name, sizeof (something));
g_free (sys_name);
return something;
}
return nothing;
}
GtkWidget *dirbrowser_new (const gchar *title)
{
Dirbrowser *dbr;
dbr = g_object_new (DIRBROWSER_TYPE, NULL);
if (title)
gtk_window_set_title (GTK_WINDOW (dbr), title);
return GTK_WIDGET (dbr);
}
void dirbrowser_entry_changed (GtkEditable *entry, gpointer user_data)
{
Dirbrowser *dbr;
gchar *location;
location = gtk_editable_get_chars (entry, 0, -1);
dbr = DIRBROWSER (user_data);
if (g_file_test (location, G_FILE_TEST_IS_DIR))
{
dirbrowser_populate_full_dir (dbr, location);
dirbrowser_select (dbr, location);
}
g_free (location);
}
void dirbrowser_cursor_changed (GtkTreeView *treeview, gpointer user_data)
{
Dirbrowser *dbr;
GtkTreeIter iter;
GtkTreeModel *store;
GtkTreeSelection *sel;
GtkTreePath *path;
gchar *fs_path;
gint i = 0;
dbr = DIRBROWSER (user_data);
g_return_if_fail (IS_DIRBROWSER (dbr));
store = gtk_tree_view_get_model (treeview);
sel = gtk_tree_view_get_selection (treeview);
g_return_if_fail (gtk_tree_selection_get_selected (sel, &store, &iter));
path = gtk_tree_model_get_path (store, &iter);
fs_path = _dirbrowser_treepath_to_fspath (path, store);
if (!gtk_tree_model_iter_n_children (store, &iter))
i = dirbrowser_populate_children (dbr, iter, fs_path);
//gtk_tree_view_expand_row (treeview, path, FALSE);
g_signal_handler_block ((gpointer) dbr->location, dbr->hid_entry_changed);
gtk_entry_set_text (GTK_ENTRY (dbr->location), fs_path);
g_signal_handler_unblock ((gpointer) dbr->location, dbr->hid_entry_changed);
g_free (fs_path);
}
gboolean dirbrowser_btnpress_event (GtkTreeView *treeview, GdkEventButton *event, gpointer user_data)
{
Dirbrowser *dbr;
GtkTreeSelection *sel;
GtkTreeModel *model;
GtkTreePath *path;
GtkTreeIter iter;
dbr = DIRBROWSER (user_data);
g_return_val_if_fail (IS_DIRBROWSER (dbr), FALSE);
model = gtk_tree_view_get_model (treeview);
sel = gtk_tree_view_get_selection (treeview);
g_return_val_if_fail (gtk_tree_selection_get_selected (sel, &model, &iter), FALSE);
if (event->type == GDK_2BUTTON_PRESS)
{
path = gtk_tree_model_get_path (model, &iter);
if (gtk_tree_view_row_expanded (treeview, path))
gtk_tree_view_collapse_row (treeview, path);
else
gtk_tree_view_expand_row (treeview, path, FALSE);
gtk_tree_path_free (path);
}
return FALSE;
}
void dirbrowser_btnhome_clicked (GtkButton *btn, gpointer data)
{
Dirbrowser *dbr;
dbr = DIRBROWSER (data);
g_return_if_fail (IS_DIRBROWSER (dbr));
gtk_entry_set_text (GTK_ENTRY (dbr->location), g_get_home_dir ());
}
/* This function is taken directly from the GTK+-2.6.9 sources to maintain compatibility with
* GTK 2.0.x */
static void
pureadmin_gtk_tree_view_expand_to_path (GtkTreeView *tree_view,
GtkTreePath *path)
{
gint i, depth;
gint *indices;
GtkTreePath *tmp;
g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
g_return_if_fail (path != NULL);
depth = gtk_tree_path_get_depth (path);
indices = gtk_tree_path_get_indices (path);
tmp = gtk_tree_path_new ();
g_return_if_fail (tmp != NULL);
for (i = 0; i < depth; i++)
{
gtk_tree_path_append_index (tmp, indices[i]);
gtk_tree_view_expand_row (tree_view, tmp, FALSE);
}
gtk_tree_path_free (tmp);
}
gboolean dirbrowser_select (Dirbrowser *dbr, const gchar *directory)
{
GtkTreeModel *model;
GtkTreeIter iter, child_iter;
GtkTreePath *path;
GtkTreeSelection *sel;
gchar **dir_v, *tmp;
gint i = 0;
gboolean found = FALSE;
g_return_val_if_fail (IS_DIRBROWSER (dbr), FALSE);
g_return_val_if_fail (g_path_is_absolute (directory), FALSE);
model = gtk_tree_view_get_model (GTK_TREE_VIEW (dbr->dir_tree));
gtk_tree_model_get_iter_first (model, &iter);
dir_v = _dirbrowser_directory_split (directory);
while (dir_v[i]/* && gtk_tree_store_iter_is_valid (GTK_TREE_STORE (model), &iter) */)
{
found = FALSE;
gtk_tree_model_get (model, &iter,
COL_FSNAME, &tmp,
-1);
if (strcmp (dir_v[i], tmp) == 0)
{
/* MATCH */
found = TRUE;
if (gtk_tree_model_iter_children (model, &child_iter, &iter))
{
if (dir_v[i+1])
memcpy (&iter, &child_iter, sizeof (GtkTreeIter));
i++;
}
else
{
g_free (tmp);
break;
}
}
else
gtk_tree_model_iter_next (model, &iter);
g_free (tmp);
}
if (found)
{
sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (dbr->dir_tree));
path = gtk_tree_model_get_path (model, &iter);
g_signal_handler_block ((gpointer) dbr->dir_tree, dbr->hid_cursor_changed);
pureadmin_gtk_tree_view_expand_to_path (GTK_TREE_VIEW (dbr->dir_tree), path);
gtk_tree_view_expand_row (GTK_TREE_VIEW (dbr->dir_tree), path, FALSE);
gtk_tree_selection_select_path (sel, path);
while (g_main_context_pending (NULL))
g_main_context_iteration (NULL, FALSE);
gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (dbr->dir_tree), path, NULL, TRUE, 0.3, 0);
g_signal_handler_unblock ((gpointer) dbr->dir_tree, dbr->hid_cursor_changed);
gtk_tree_path_free (path);
}
return TRUE;
}
void dirbrowser_populate_full_dir (Dirbrowser *dbr, const char *directory)
{
GtkTreeModel *model;
GtkTreeIter iter, child_iter;
gchar **dir_v, *tmp;
GString *cur_dir;
gint i = 0, count;
g_return_if_fail (IS_DIRBROWSER (dbr));
g_return_if_fail (g_path_is_absolute (directory));
model = gtk_tree_view_get_model (GTK_TREE_VIEW (dbr->dir_tree));
gtk_tree_model_get_iter_first (model, &iter);
cur_dir = g_string_new ("");
dir_v = _dirbrowser_directory_split (directory);
while (dir_v[i])
{
gtk_tree_model_get (model, &iter,
COL_FSNAME, &tmp,
-1);
if (strcmp (dir_v[i], tmp) == 0)
{
cur_dir = g_string_append (cur_dir, dir_v[i]);
if (!gtk_tree_model_iter_n_children (model, &iter))
{
count = dirbrowser_populate_children (dbr, iter, cur_dir->str);
if (count < 1)
break;
}
gtk_tree_model_iter_children (model, &child_iter, &iter);
memcpy (&iter, &child_iter, sizeof (GtkTreeIter));
if (*dir_v[i] != '/')
cur_dir = g_string_append_c (cur_dir, '/');
i++;
}
else
gtk_tree_model_iter_next (model, &iter);
}
g_strfreev (dir_v);
g_string_free (cur_dir, TRUE);
}
gint dirbrowser_populate_children (Dirbrowser *dbr, GtkTreeIter parent_iter, const gchar *directory)
{
GtkTreeModel *model;
GtkTreeIter child_iter;
gchar *utf8_entry, *entry;
GList *dirlist, *node;
gint count = 0;
g_return_val_if_fail (IS_DIRBROWSER (dbr), 0);
model = gtk_tree_view_get_model (GTK_TREE_VIEW (dbr->dir_tree));
g_return_val_if_fail (g_path_is_absolute (directory) || model != NULL , 0);
node = dirlist = _dirbrowser_get_dircontents (directory);
g_return_val_if_fail (dirlist != NULL, 0);
do
{
entry = (gchar *) node->data;
utf8_entry = g_filename_to_utf8 (entry, -1, NULL, NULL, NULL);
if (utf8_entry && g_utf8_validate (utf8_entry, -1, NULL))
{
count++;
gtk_tree_store_append (GTK_TREE_STORE (model), &child_iter, &parent_iter);
gtk_tree_store_set (GTK_TREE_STORE (model), &child_iter,
COL_IMAGE, dbr->icon,
COL_NAME, utf8_entry,
COL_FSNAME, entry,
-1);
}
else
g_warning ("%s: Invalid entry: %s\n", __FUNCTION__, entry);
g_free (utf8_entry);
g_free (node->data);
} while ((node = g_list_next(node)));
g_list_free (dirlist);
return count;
}
/* Returns the contents of a directory in a sorted GList */
GList *_dirbrowser_get_dircontents (const gchar *directory)
{
const gchar *entry;
gchar *full_path;
GDir *dir;
GList *retval = NULL;
dir = g_dir_open (directory, 0, NULL);
g_return_val_if_fail (dir != NULL, NULL);
while ((entry = g_dir_read_name (dir)))
{
full_path = g_strdup_printf ("%s/%s",directory, entry);
/* FIXME: strcasecmp needs to be replaced here! */
if (g_file_test (full_path, G_FILE_TEST_IS_DIR) && *entry != '.')
retval = g_list_insert_sorted (retval, g_strdup (entry), (GCompareFunc) g_strcasecmp);
g_free (full_path);
}
g_dir_close (dir);
return g_list_first (retval);
}
gchar **_dirbrowser_directory_split (const gchar *directory)
{
gchar **ret;
gchar **tmp_v;
gint i = 0, j = 0;
tmp_v = g_strsplit (directory, "/", 0);
if (!tmp_v)
return g_strsplit ("", "/", 0);
while (tmp_v[i++])
; /* Check how many parts we have.. */
ret = g_new0 (gchar *, i);
/* Was: (gchar **) g_malloc0 (i * sizeof (gchar *)); */
i = -1;
ret[j++] = g_strdup ("/");
while (tmp_v[++i])
{
if (*tmp_v[i] == '\0')
continue;
ret[j++] = g_strdup (tmp_v[i]);
}
g_strfreev (tmp_v);
return ret;
}
gchar *_dirbrowser_treepath_to_fspath (const GtkTreePath *c_path, GtkTreeModel *model)
{
GString *fs_path;
GtkTreeIter iter;
GtkTreePath *path;
gchar *ret, *entry;
path = gtk_tree_path_copy (c_path);
if (gtk_tree_path_get_depth (path) == 1)
return g_strdup ("/");
fs_path = g_string_new ("");
while (gtk_tree_path_get_depth (path) > 1)
{
gtk_tree_model_get_iter (model, &iter, path);
gtk_tree_model_get (model, &iter,
COL_FSNAME, &entry,
-1);
g_string_prepend (fs_path, entry);
if (*entry != '/')
g_string_prepend_c (fs_path, '/');
gtk_tree_path_up (path);
}
ret = fs_path->str;
g_string_free (fs_path, FALSE);
gtk_tree_path_free (path);
return ret;
}
syntax highlighted by Code2HTML, v. 0.9.1