grim/guifications1
Clone
Summary
Browse
Changes
Graph
whats the point of adding accel keys to the menus if you can't use 'em! this fixes that..
2003-12-29, grim
40f5c1cf6282
whats the point of adding accel keys to the menus if you can't use 'em! this fixes that..
/*
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
}