# HG changeset patch # User nenolod # Date 1165225192 28800 # Node ID 456c74b6880a7751f68d5a9e5b8438a338ddcd90 # Parent 04961c9a5242fa3c4b930ea3e8c4eba4a11ca607 [svn] - bleah, put dirbrowser back diff -r 04961c9a5242 -r 456c74b6880a ChangeLog --- a/ChangeLog Mon Dec 04 01:37:47 2006 -0800 +++ b/ChangeLog Mon Dec 04 01:39:52 2006 -0800 @@ -1,3 +1,12 @@ +2006-12-04 09:37:47 +0000 William Pitcock + revision [3093] + - document the formatter class + + trunk/doc/libaudacious/tmpl/formatter.sgml | 4 - + trunk/libaudacious/formatter.c | 59 ++++++++++++++++++++++++++++- + 2 files changed, 60 insertions(+), 3 deletions(-) + + 2006-12-04 09:30:01 +0000 William Pitcock revision [3091] - bye bye dirbrowser diff -r 04961c9a5242 -r 456c74b6880a libaudacious/Makefile --- a/libaudacious/Makefile Mon Dec 04 01:37:47 2006 -0800 +++ b/libaudacious/Makefile Mon Dec 04 01:39:52 2006 -0800 @@ -27,6 +27,7 @@ rcfile.c \ $(VFS_SRC) \ beepctrl.c \ + dirbrowser.c \ util.c \ formatter.c \ titlestring.c \ @@ -37,7 +38,7 @@ HEADERS = \ vfs.h rcfile.h configdb.h \ - beepctrl.h \ + beepctrl.h dirbrowser.h \ formatter.h titlestring.h xconvert.h xml_document.h include ../mk/objective.mk diff -r 04961c9a5242 -r 456c74b6880a libaudacious/dirbrowser.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libaudacious/dirbrowser.c Mon Dec 04 01:39:52 2006 -0800 @@ -0,0 +1,400 @@ +/* XMMS - Cross-platform multimedia player + * Copyright (C) 1998-2002 Peter Alm, Mikael Alm, Olle Hallnas, + * Thomas Nilsson and 4Front Technologies + * Copyright (C) 1999-2002 Haavard Kvaalen + * + * 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 Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#define GETTEXT_PACKAGE PACKAGE + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + + +/* XPM */ +static gchar *folder[] = { + "16 16 16 1", + " c None", + ". c #f4f7e4", + "X c #dee4b5", + "o c #e1e7b9", + "O c #c6cba4", + "+ c #dce2b8", + "@ c #e9e9ec", + "# c #d3d8ae", + "$ c #d8daca", + "% c #b2b2b5", + "& c #767862", + "* c #e3e6c3", + "= c #1b1b1a", + "- c #939684", + "; c #555555", + ": c #000000", + " ", + " ", + " :::: ", + " :.@@O: ", + ":-&&&&&::::: ", + ":.@@@@@*$O#O= ", + ":@*+XXXX+##O: ", + ":.*#oooXXXXX: ", + ":@+XoXXXXXX#: ", + ":@*ooXXXXXX#: ", + ":@**XXXXXXX#: ", + ":@*XXXXXXXX%: ", + ":$.*OOOOOO%-: ", + " ;::::::::::: ", + " ", + " " +}; + +/* Icon by Jakub Steiner */ + +/* XPM */ +static gchar *ofolder[] = { + "16 16 16 1", + " c None", + ". c #a9ad93", + "X c #60634d", + "o c #dee4b5", + "O c #9ca085", + "+ c #0c0d04", + "@ c #2f2f31", + "# c #3b3d2c", + "$ c #c8cda2", + "% c #e6e6e9", + "& c #b3b5a5", + "* c #80826d", + "= c #292a1c", + "- c #fefef6", + "; c #8f937b", + ": c #000000", + " ", + " ", + " :::: ", + " :-%%&: ", + ":-;;;OX::::: ", + ":-;;;;O;O;&.: ", + ":-*X##@@@@@=#: ", + ":%*+-%%ooooooO: ", + ":%X;%ooooooo.*: ", + ":.+-%oooooooO: ", + ":*O-oooooooo*: ", + ":O-oooooooo.: ", + ":*-%$$$$$$OX: ", + " ::::::::::: ", + " ", + " " +}; + +#define NODE_SPACING 4 + +typedef void (*db_handler_t) (char *); + +static GdkPixmap *folder_pixmap = NULL, *ofolder_pixmap; +static GdkBitmap *folder_mask, *ofolder_mask; + +struct dirnode { + guint scanned:1; + gchar *path; +}; + +static gboolean +check_for_subdir(gchar * path) +{ + DIR *dir; + struct dirent *dirent; + struct stat statbuf; + gchar *npath; + + if ((dir = opendir(path)) != NULL) { + while ((dirent = readdir(dir)) != NULL) { + if (dirent->d_name[0] == '.') + continue; + + npath = g_strconcat(path, dirent->d_name, NULL); + if (stat(npath, &statbuf) != -1 && S_ISDIR(statbuf.st_mode)) { + g_free(npath); + closedir(dir); + return TRUE; + } + g_free(npath); + } + closedir(dir); + } + return FALSE; +} + +static void +destroy_cb(gpointer data) +{ + struct dirnode *node = data; + + g_free(node->path); + g_free(node); +} + +static void +add_dir(GtkCTree * tree, GtkCTreeNode * pnode, gchar * parent, gchar * dir) +{ + struct stat statbuf; + gchar *path; + + /* Don't show hidden dirs, nor . and .. */ + if (dir[0] == '.') + return; + + path = g_strconcat(parent, dir, NULL); + if (stat(path, &statbuf) != -1 && S_ISDIR(statbuf.st_mode)) { + gboolean has_subdir; + gchar *text = ""; + GtkCTreeNode *node; + struct dirnode *dirnode = g_new0(struct dirnode, 1); + dirnode->path = g_strconcat(path, "/", NULL); + has_subdir = check_for_subdir(dirnode->path); + node = gtk_ctree_insert_node(tree, pnode, NULL, &dir, + NODE_SPACING, folder_pixmap, + folder_mask, ofolder_pixmap, + ofolder_mask, !has_subdir, FALSE); + gtk_ctree_node_set_row_data_full(tree, node, dirnode, destroy_cb); + if (has_subdir) + gtk_ctree_insert_node(tree, node, NULL, &text, + NODE_SPACING, NULL, NULL, + NULL, NULL, FALSE, FALSE); + } + g_free(path); +} + +static void +expand_cb(GtkWidget * widget, GtkCTreeNode * parent_node) +{ + struct dirent *dirent; + GtkCTree *tree = GTK_CTREE(widget); + struct dirnode *parent_dirnode; + + parent_dirnode = gtk_ctree_node_get_row_data(tree, parent_node); + if (!parent_dirnode->scanned) { + DIR *dir; + + gtk_clist_freeze(GTK_CLIST(widget)); + gtk_ctree_remove_node(tree, GTK_CTREE_ROW(parent_node)->children); + if ((dir = opendir(parent_dirnode->path)) != NULL) { + while ((dirent = readdir(dir)) != NULL) { + add_dir(tree, parent_node, + parent_dirnode->path, dirent->d_name); + } + closedir(dir); + gtk_ctree_sort_node(tree, parent_node); + } + gtk_clist_thaw(GTK_CLIST(widget)); + parent_dirnode->scanned = TRUE; + } +} + +static void +select_row_cb(GtkWidget * widget, gint row, gint column, + GdkEventButton * bevent, gpointer data) +{ + struct dirnode *dirnode; + GtkCTreeNode *node; + db_handler_t handler; + + if (bevent && bevent->type == GDK_2BUTTON_PRESS) { + node = gtk_ctree_node_nth(GTK_CTREE(widget), row); + dirnode = gtk_ctree_node_get_row_data(GTK_CTREE(widget), node); + handler = (db_handler_t) gtk_object_get_user_data(GTK_OBJECT(widget)); + if (handler) + handler(dirnode->path); + } +} + +static void +show_cb(GtkWidget * widget, gpointer data) +{ + GtkCTree *tree = GTK_CTREE(data); + GtkCTreeNode *node = gtk_object_get_data(GTK_OBJECT(tree), + "selected_node"); + + if (node) + gtk_ctree_node_moveto(tree, node, -1, 0.6, 0); +} + +static void +ok_clicked(GtkWidget * widget, GtkWidget * tree) +{ + GtkCTreeNode *node; + struct dirnode *dirnode; + GList *list_node; + GtkWidget *window; + db_handler_t handler; + + window = gtk_object_get_user_data(GTK_OBJECT(widget)); + gtk_widget_hide(window); + list_node = GTK_CLIST(tree)->selection; + while (list_node) { + node = list_node->data; + dirnode = gtk_ctree_node_get_row_data(GTK_CTREE(tree), node); + handler = (db_handler_t) gtk_object_get_user_data(GTK_OBJECT(tree)); + if (handler) + handler(dirnode->path); + list_node = g_list_next(list_node); + } + gtk_widget_destroy(window); + +} + +GtkWidget * +xmms_create_dir_browser(gchar * title, gchar * current_path, + GtkSelectionMode mode, void (*handler) (gchar *)) +{ + GtkWidget *window, *scroll_win, *tree, *vbox, *bbox, *ok, *cancel, *sep; + gchar *root_text = "/", *text = ""; + GtkCTreeNode *root_node, *node, *selected_node = NULL; + GtkCTree *ctree; + struct dirnode *dirnode; + + window = gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); + gtk_window_set_title(GTK_WINDOW(window), title); + gtk_window_set_type_hint(GTK_WINDOW(window), GDK_WINDOW_TYPE_HINT_DIALOG); + gtk_container_border_width(GTK_CONTAINER(window), 10); + + vbox = gtk_vbox_new(FALSE, 10); + gtk_container_add(GTK_CONTAINER(window), vbox); + + scroll_win = gtk_scrolled_window_new(NULL, NULL); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll_win), + GTK_POLICY_AUTOMATIC, + GTK_POLICY_AUTOMATIC); + gtk_widget_set_usize(scroll_win, 450, 400); + gtk_box_pack_start(GTK_BOX(vbox), scroll_win, TRUE, TRUE, 0); + gtk_widget_show(scroll_win); + + gtk_widget_realize(window); + if (!folder_pixmap) { + folder_pixmap = gdk_pixmap_create_from_xpm_d(window->window, + &folder_mask, + NULL, folder); + ofolder_pixmap = gdk_pixmap_create_from_xpm_d(window->window, + &ofolder_mask, + NULL, ofolder); + } + + tree = gtk_ctree_new(1, 0); + ctree = GTK_CTREE(tree); + gtk_clist_set_column_auto_resize(GTK_CLIST(tree), 0, TRUE); + gtk_clist_set_selection_mode(GTK_CLIST(tree), mode); + gtk_ctree_set_line_style(ctree, GTK_CTREE_LINES_DOTTED); + g_signal_connect(G_OBJECT(tree), "tree_expand", + G_CALLBACK(expand_cb), NULL); + g_signal_connect(G_OBJECT(tree), "select_row", + G_CALLBACK(select_row_cb), NULL); + g_signal_connect(G_OBJECT(window), "show", G_CALLBACK(show_cb), tree); + gtk_container_add(GTK_CONTAINER(scroll_win), tree); + gtk_object_set_user_data(GTK_OBJECT(tree), (void *) handler); + + root_node = gtk_ctree_insert_node(ctree, NULL, NULL, + &root_text, NODE_SPACING, + folder_pixmap, folder_mask, + ofolder_pixmap, ofolder_mask, + FALSE, FALSE); + dirnode = g_new0(struct dirnode, 1); + dirnode->path = g_strdup(G_DIR_SEPARATOR_S); + gtk_ctree_node_set_row_data_full(ctree, root_node, dirnode, destroy_cb); + node = gtk_ctree_insert_node(ctree, root_node, NULL, + &text, 4, NULL, NULL, NULL, + NULL, TRUE, TRUE); + gtk_ctree_expand(ctree, root_node); + gtk_widget_show(tree); + + sep = gtk_hseparator_new(); + gtk_box_pack_start(GTK_BOX(vbox), sep, FALSE, FALSE, 0); + gtk_widget_show(sep); + + bbox = gtk_hbutton_box_new(); + gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END); + gtk_button_box_set_spacing(GTK_BUTTON_BOX(bbox), 5); + + ok = gtk_button_new_from_stock(GTK_STOCK_OK); + gtk_object_set_user_data(GTK_OBJECT(ok), window); + GTK_WIDGET_SET_FLAGS(ok, GTK_CAN_DEFAULT); + gtk_window_set_default(GTK_WINDOW(window), ok); + gtk_box_pack_start(GTK_BOX(bbox), ok, TRUE, TRUE, 0); + g_signal_connect(G_OBJECT(ok), "clicked", G_CALLBACK(ok_clicked), tree); + gtk_widget_show(ok); + + cancel = gtk_button_new_from_stock(GTK_STOCK_CANCEL); + GTK_WIDGET_SET_FLAGS(cancel, GTK_CAN_DEFAULT); + gtk_box_pack_start(GTK_BOX(bbox), cancel, TRUE, TRUE, 0); + g_signal_connect_swapped(G_OBJECT(cancel), "clicked", + G_CALLBACK(gtk_widget_destroy), + GTK_OBJECT(window)); + gtk_widget_show(cancel); + + gtk_box_pack_start(GTK_BOX(vbox), bbox, FALSE, FALSE, 0); + gtk_widget_show(bbox); + gtk_widget_show(vbox); + + if (current_path && *current_path) { + gchar **dir; + gint i; + + dir = g_strsplit(current_path, G_DIR_SEPARATOR_S, 0); + node = root_node; + for (i = 0; dir[i] != NULL; i++) { + if (dir[i][0] == '\0') + continue; + + for (node = GTK_CTREE_ROW(node)->children; node != NULL; + node = GTK_CTREE_ROW(node)->sibling) { + gchar *tmp; + if (gtk_ctree_node_get_pixtext(ctree, node, 0, + &tmp, NULL, NULL, NULL)) + if (!strcmp(dir[i], tmp)) + break; + } + if (!node) + break; + if (!GTK_CTREE_ROW(node)->is_leaf && dir[i + 1]) + gtk_ctree_expand(ctree, node); + else { + selected_node = node; + break; + } + } + g_strfreev(dir); + } + + if (!selected_node) + selected_node = root_node; + + gtk_ctree_select(ctree, selected_node); + gtk_object_set_data(GTK_OBJECT(tree), "selected_node", selected_node); + + return window; +} diff -r 04961c9a5242 -r 456c74b6880a libaudacious/dirbrowser.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libaudacious/dirbrowser.h Mon Dec 04 01:39:52 2006 -0800 @@ -0,0 +1,34 @@ + +/* XMMS - Cross-platform multimedia player + * Copyright (C) 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson and 4Front Technologies + * + * 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 Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#ifndef XMMS_DIRBROWSER_H +#define XMMS_DIRBROWSER_H + +#include +#include + + +G_BEGIN_DECLS + +GtkWidget *xmms_create_dir_browser(gchar * title, gchar * current_path, + GtkSelectionMode mode, + void (*handler) (gchar *)); + +G_END_DECLS + +#endif