grim/guifications1

6262e0b52b3f
hmmm cleanup or new code.. more cleanup
/*
Guifications - The notification plugin to end all notification plugins!
Copyright (C) 2003 Gary Kramlich
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.
*/
#include <stdio.h>
#include <gtk/gtk.h>
#include <gdk/gdk.h>
#include <string.h>
#include <math.h>
#ifdef _WIN32
#include <windows.h>
#endif
#include "grimdirtreeview.h"
#define DIR_COL_ICON 0
#define DIR_COL_TEXT 1
#define DIR_COL_PATH 2
#define DIR_COL_COUNT 3
/* folder icons taken from galeon */
/* XPM */
static const char * folder_xpm[] = {
"16 16 61 1",
" c None",
". c #000000",
"+ c #8D8E8C",
"@ c #E4E5DF",
"# c #D5D6CB",
"$ c #D6D7CA",
"% c #A3A39D",
"& c #F5F6F0",
"* c #ADB198",
"= c #C2C6A9",
"- c #C0C3A7",
"; c #B4B89D",
"> c #6D705F",
", c #EAECDB",
"' c #F6F6F4",
") c #EAECDA",
"! c #E8EAD8",
"~ c #E9EBDB",
"{ c #E6E8D5",
"] c #E5E8D4",
"^ c #E4E7D2",
"/ c #C7C9B6",
"( c #F7F7F7",
"_ c #DADEBF",
": c #DADEBE",
"< c #D8DCBC",
"[ c #D6DBB9",
"} c #D5D9B7",
"| c #D3D7B4",
"1 c #CFD4AF",
"2 c #CDD2AD",
"3 c #CBD1AA",
"4 c #95997C",
"5 c #F3F3EA",
"6 c #F3F4EA",
"7 c #D1D6B2",
"8 c #CACFA8",
"9 c #C8CDA5",
"0 c #929778",
"a c #F1F3E9",
"b c #C6CCA3",
"c c #C4CAA0",
"d c #8F9474",
"e c #EFF1E5",
"f c #CED3AF",
"g c #CED3AE",
"h c #CBD0AB",
"i c #CACFA9",
"j c #C9CEA7",
"k c #C6CCA4",
"l c #C5CAA1",
"m c #C5CAA2",
"n c #8D9270",
"o c #EBECDE",
"p c #C2C89D",
"q c #C1C79B",
"r c #BFC598",
"s c #C9CCB9",
"t c #919576",
"u c #8F9372",
"v c #666951",
" ",
" ",
" .... ",
" +@#$%. ",
" .&*=-;>..... ",
" .,',,)!~{]^/. ",
" .(_:<[}|1234. ",
" .5_:<[}|1234. ",
" .6<[}|713890. ",
" .a}|71239bcd. ",
" .efg2hijklmn. ",
" .o89bcpqrrrn. ",
" .s0tdunnnnnv. ",
" ........... ",
" ",
" "};
/* XPM */
static const char * folder_open_xpm[] = {
"16 16 64 1",
" c None",
". c #000000",
"+ c #E4E5DF",
"@ c #D5D6CB",
"# c #D6D7CA",
"$ c #A3A39D",
"% c #F5F6F0",
"& c #8D907B",
"* c #92957E",
"= c #90937D",
"- c #979B84",
"; c #6D705F",
"> c #EAECDB",
", c #8A8C7D",
"' c #8E917B",
") c #91947F",
"! c #8B8E7A",
"~ c #999B87",
"{ c #919480",
"] c #989B86",
"^ c #B1B4A2",
"/ c #A2A394",
"( c #F7F7F7",
"_ c #878A75",
": c #666858",
"< c #4B4D3F",
"[ c #4D4F40",
"} c #404135",
"| c #424337",
"1 c #434437",
"2 c #404236",
"3 c #3C3D32",
"4 c #48493C",
"5 c #1A1A16",
"6 c #C6C6BE",
"7 c #848672",
"8 c #25261F",
"9 c #F1F2E9",
"0 c #DDE0C7",
"a c #D6DABB",
"b c #CDD2AC",
"c c #C7CCA7",
"d c #989C80",
"e c #C6C7BE",
"f c #5F6152",
"g c #888980",
"h c #A7AB8C",
"i c #878A70",
"j c #9FA19A",
"k c #EFF0E5",
"l c #9EA284",
"m c #80817B",
"n c #96968D",
"o c #E3E5D1",
"p c #83866D",
"q c #97998D",
"r c #EDEFE2",
"s c #A2A688",
"t c #767671",
"u c #E7E9DA",
"v c #D1D3BD",
"w c #BBBF9D",
"x c #989B80",
"y c #6E715C",
" ",
" ",
" .... ",
" .+@#$. ",
" .%&*=-;..... ",
" .>,')!~{]{^/. ",
" .(_:<[}||12345 ",
" .67890abbbbbcd.",
" .efg0bbbbbbbhi.",
" .j8kabbbbbbbl. ",
" .mnobbbbbbbbp. ",
" .qrbbbbbbbbs. ",
" .tuvwwwwwwxy. ",
" ........... ",
" ",
" "};
static void grim_dir_tree_view_class_init(GrimDirTreeViewClass *klass);
static void grim_dir_tree_view_init(GrimDirTreeView *dir_tree_view);
static void add_dir(GtkTreeStore *store, GtkTreeIter *parent, gchar *parent_path, gchar *child_path);
static void expand_cb(GrimDirTreeView *dir_tree_view, GtkTreeIter *iter, GtkTreePath *path, gpointer data);
static void collapse_cb(GrimDirTreeView *dir_tree_view, GtkTreeIter *iter, GtkTreePath *path, gpointer data);
static void add_root_node(GrimDirTreeView *dir_tree_view);
static gboolean has_subdir(gchar *path);
GType
grim_dir_tree_view_get_type (void) {
static GType dir_tree_view_type = 0;
if (!dir_tree_view_type) {
static const GTypeInfo dir_tree_view_type_info = {
sizeof (GrimDirTreeViewClass),
NULL, /* base_init */
NULL, /* base_finalize */
(GClassInitFunc) grim_dir_tree_view_class_init,
NULL, /* class_finalize */
NULL, /* class_data */
sizeof (GrimDirTreeView),
0, /* n_preallocs */
(GInstanceInitFunc) grim_dir_tree_view_init,
};
dir_tree_view_type = g_type_register_static(GTK_TYPE_TREE_VIEW,
"GrimDirTreeView",
&dir_tree_view_type_info,
0);
}
return dir_tree_view_type;
}
static void
grim_dir_tree_view_class_init(GrimDirTreeViewClass *klass) {
}
static void
grim_dir_tree_view_init(GrimDirTreeView *dir_tree_view) {
GtkTreeViewColumn *directory;
GtkCellRenderer *renderer;
/* initialize variables */
dir_tree_view->store = gtk_tree_store_new(DIR_COL_COUNT, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING);
/* add root node */
add_root_node(dir_tree_view);
/* set globals for tree view */
gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(dir_tree_view), FALSE);
/* create and add the directory column to the tree view */
directory = gtk_tree_view_column_new();
//gtk_tree_view_column_set_alignment(directory, 0);
gtk_tree_view_append_column(GTK_TREE_VIEW(&dir_tree_view->tree_view), directory);
/* create and pack the cell renderer(s) */
renderer = gtk_cell_renderer_pixbuf_new();
gtk_tree_view_column_pack_start(directory, renderer, FALSE);
gtk_tree_view_column_add_attribute(directory, renderer, "pixbuf", DIR_COL_ICON);
renderer = gtk_cell_renderer_text_new();
gtk_tree_view_column_pack_start(directory, renderer, FALSE);
gtk_tree_view_column_add_attribute(directory, renderer, "text", DIR_COL_TEXT);
/* connect signals */
g_signal_connect(G_OBJECT(dir_tree_view), "row_expanded", G_CALLBACK(expand_cb), NULL);
g_signal_connect(G_OBJECT(dir_tree_view), "row_collapsed", G_CALLBACK(collapse_cb), NULL);
/* attach the store to the tree view */
gtk_tree_view_set_model(GTK_TREE_VIEW(&dir_tree_view->tree_view), GTK_TREE_MODEL(dir_tree_view->store));
}
static gboolean
has_subdir(gchar *path) {
GDir *directory;
gchar *new_path, *name;
if (g_path_is_absolute(path)) {
if ((directory = g_dir_open(path, 0, FALSE)) != NULL) {
while ((name = g_strdup(g_dir_read_name(directory))) != NULL) {
/* add check for show hidden when I add the property */
if (name[0] == '.') {
g_free(name);
continue;
}
if (path != NULL)
new_path = g_strconcat(path, name, NULL);
else
new_path = g_strdup(name);
if (g_file_test(new_path, G_FILE_TEST_IS_DIR)) {
g_free(new_path);
g_dir_close(directory);
return TRUE;
}
g_free(name);
g_free(new_path);
}
g_dir_close(directory);
}
}
return FALSE;
}
static void
add_dir(GtkTreeStore *store, GtkTreeIter *parent, gchar *parent_path, gchar *child_path) {
GdkPixbuf *pixbuf;
GtkTreeIter current, child;
gchar *new_path;
/* tweak when show hidden property is added */
if (child_path[0] == '.')
return;
pixbuf = gdk_pixbuf_new_from_xpm_data(folder_xpm);
if (parent_path != NULL)
new_path = g_strconcat(parent_path, child_path, G_DIR_SEPARATOR_S, NULL);
else
if (g_ascii_strcasecmp(child_path, G_DIR_SEPARATOR_S) == 0)
new_path = g_strdup(child_path);
else
new_path = g_strconcat(child_path, G_DIR_SEPARATOR_S, NULL);
if (g_file_test(new_path, G_FILE_TEST_IS_DIR)) {
gtk_tree_store_append(store, &current, parent);
gtk_tree_store_set(store, &current, DIR_COL_ICON, pixbuf, DIR_COL_TEXT, child_path, DIR_COL_PATH, new_path, -1);
if (has_subdir(new_path)) {
gtk_tree_store_append(store, &child, &current);
gtk_tree_store_set(store, &child, DIR_COL_TEXT, "", DIR_COL_PATH, NULL, -1);
}
}
g_object_unref(pixbuf);
g_free(new_path);
}
static void
expand_cb(GrimDirTreeView *dir_tree_view, GtkTreeIter *iter, GtkTreePath *path, gpointer data) {
GdkPixbuf *pixbuf;
GdkCursor *cursor;
GtkTreeIter child;
GtkTreeSortable *sortable;
GDir *directory;
gchar *dir_path, *child_path = NULL;
gchar *name;
gtk_tree_model_get(GTK_TREE_MODEL(dir_tree_view->store), iter, DIR_COL_PATH, &dir_path, -1);
pixbuf = gdk_pixbuf_new_from_xpm_data(folder_open_xpm);
gtk_tree_store_set(dir_tree_view->store, iter, DIR_COL_ICON, pixbuf, -1);
g_object_unref(pixbuf);
if (gtk_tree_model_iter_children(GTK_TREE_MODEL(dir_tree_view->store), &child, iter)) {
gtk_tree_model_get(GTK_TREE_MODEL(dir_tree_view->store), &child, DIR_COL_PATH, &child_path);
if (child_path == NULL) {
if ((directory = g_dir_open(dir_path, 0, NULL)) != NULL) {
cursor = gdk_cursor_new(GDK_WATCH);
if (!GTK_WIDGET_REALIZED(dir_tree_view))
gtk_widget_realize(GTK_WIDGET(dir_tree_view));
gdk_window_set_cursor(GTK_WIDGET(dir_tree_view)->window, cursor);
gtk_main_iteration();
while ((name = g_strdup(g_dir_read_name(directory))) != NULL) {
add_dir(dir_tree_view->store, iter, dir_path, name);
g_free(name);
}
g_dir_close(directory);
gdk_window_set_cursor(GTK_WIDGET(dir_tree_view)->window, NULL);
gdk_cursor_unref(cursor);
}
gtk_tree_store_remove(dir_tree_view->store, &child);
sortable = GTK_TREE_SORTABLE(dir_tree_view->store);
gtk_tree_sortable_set_sort_column_id(sortable, DIR_COL_TEXT, GTK_SORT_ASCENDING);
}
}
}
static void
collapse_cb(GrimDirTreeView *dir_tree_view, GtkTreeIter *iter, GtkTreePath *path, gpointer data) {
GdkPixbuf *pixbuf;
GtkTreeIter holder, child;
gint count, i;
pixbuf = gdk_pixbuf_new_from_xpm_data(folder_xpm);
gtk_tree_store_set(dir_tree_view->store, iter, DIR_COL_ICON, pixbuf, -1);
g_object_unref(pixbuf);
count = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(dir_tree_view->store), iter);
gtk_tree_store_append(dir_tree_view->store, &holder, iter);
gtk_tree_store_set(dir_tree_view->store, &holder, DIR_COL_PATH, NULL, -1);
for (i = 0; i < count; i++) {
gtk_tree_model_iter_children(GTK_TREE_MODEL(dir_tree_view->store), &child, iter);
gtk_tree_store_remove(dir_tree_view->store, &child);
}
}
GtkWidget *
grim_dir_tree_view_new() {
return GTK_WIDGET (g_object_new(grim_dir_tree_view_get_type(), NULL));
}
const gchar *
grim_dir_tree_view_get_path(GrimDirTreeView *dir_tree_view) {
GtkTreeSelection *selection;
GtkTreeIter selected;
gchar *path = NULL, *ret_path;
selection = gtk_tree_view_get_selection(&dir_tree_view->tree_view);
if (gtk_tree_selection_get_selected(selection, NULL, &selected)) {
gtk_tree_model_get(GTK_TREE_MODEL(dir_tree_view->store), &selected, DIR_COL_PATH, &path, -1);
if (path[0] == path[1] && path[0] == G_DIR_SEPARATOR)
path++;
}
ret_path = g_strdup(path);
return ret_path;
}
gboolean
grim_dir_tree_view_set_path(GrimDirTreeView *dir_tree_view, const gchar *path) {
GtkTreeSelection *selection;
GtkTreePath *tree_path;
GtkTreeIter parent, child;
gchar **directories;
gchar *search_path = NULL, *new_path = NULL, *child_path = NULL;
gint dir = 0;
directories = g_strsplit(path, G_DIR_SEPARATOR_S, 0);
while (directories[dir] != NULL) {
if (dir == 0) {
search_path = g_strdup(G_DIR_SEPARATOR_S);
gtk_tree_model_get_iter_first(GTK_TREE_MODEL(dir_tree_view->store), &parent);
tree_path = gtk_tree_model_get_path(GTK_TREE_MODEL(dir_tree_view->store), &parent);
gtk_tree_view_expand_row(GTK_TREE_VIEW(dir_tree_view), tree_path, TRUE);
gtk_tree_path_free(tree_path);
dir++;
}
new_path = g_strdup_printf("%s%s%s", search_path, directories[dir], G_DIR_SEPARATOR_S);
if(gtk_tree_model_iter_children(GTK_TREE_MODEL(dir_tree_view->store), &child, &parent)) {
g_free(search_path);
search_path = g_strdup(new_path);
g_free(new_path);
while (1) {
gtk_tree_model_get(GTK_TREE_MODEL(dir_tree_view->store), &child, DIR_COL_PATH, &child_path, -1);
if (g_ascii_strcasecmp(search_path, child_path) == 0) {
if (g_ascii_strncasecmp(path, child_path, strlen(path)) != 0) {
tree_path = gtk_tree_model_get_path(GTK_TREE_MODEL(dir_tree_view->store), &child);
gtk_tree_view_expand_row(GTK_TREE_VIEW(dir_tree_view), tree_path, TRUE);
gtk_tree_path_free(tree_path);
parent = child;
}
break;
}
if (!gtk_tree_model_iter_next(GTK_TREE_MODEL(dir_tree_view->store), &child)) {
g_free(search_path);
g_strfreev(directories);
return FALSE;
break;
}
}
}
dir++;
}
if (search_path != NULL)
g_free(search_path);
g_strfreev(directories);
gtk_widget_grab_focus(GTK_WIDGET(dir_tree_view));
selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(dir_tree_view));
gtk_tree_selection_unselect_all(selection);
gtk_tree_selection_select_iter(selection, &child);
return FALSE;
}
void
grim_dir_tree_view_set_show_hidden(GrimDirTreeView *dir_tree_view, gboolean value) {
const gchar *path;
dir_tree_view->show_hidden = value;
path = grim_dir_tree_view_get_path(dir_tree_view);
gtk_tree_store_clear(dir_tree_view->store);
add_root_node(dir_tree_view);
}
gboolean
grim_dir_tree_view_get_show_hidden(GrimDirTreeView *dir_tree_view) {
return dir_tree_view->show_hidden;
}
static void
add_root_node(GrimDirTreeView *dir_tree_view) {
#ifdef _WIN32
gchar *drive;
gint i = 0;
guint drives = 0;
drives = GetLogicalDrives();
for (i = 0; i < 32; i++) {
if ((drives & (int)exp2(i)) == exp2(i)) {
drive = g_strdup_printf("%c:\\", 65 + i);
add_dir(dir_tree_view->store, NULL, NULL, drive);
g_free(drive);
}
}
#else
add_dir(dir_tree_view->store, NULL, NULL, G_DIR_SEPARATOR_S);
#endif
}