1 /*
2  * Based on code from gtk-theme-switch2.
3  * Copyright Maher Awamy <muhri@muhri.net>
4  *           Aaron Lehman <aaronl@vitelus.com>
5  */
6 
7 #include <stdlib.h>
8 #include <dirent.h>
9 #include <unistd.h>
10 #include <string.h>
11 #include <sys/types.h>
12 #include <sys/stat.h>
13 #include <errno.h>
14 
15 #include <glib.h>
16 #include <gtk/gtk.h>
17 
18 #include "themes.h"
19 
20 GtkSettings *settings;
21 
22 /* Sets rc_file to the rc_file of the theme if the result is true.
23  * It is the caller's repsonsibility to free rc_file */
24 static gboolean
is_themedir(gchar * path)25 is_themedir (gchar *path)
26 {
27 	gboolean is_gtk_theme = FALSE;
28 	gchar *test_rc_file;
29 	struct stat info;
30 
31 	test_rc_file = g_strdup_printf ("%s/gtk-2.0/gtkrc",path);
32 	if (stat(test_rc_file, &info) == 0 && (S_ISREG(info.st_mode) || S_ISLNK(info.st_mode)))
33 		is_gtk_theme = TRUE;
34 
35 	g_free (test_rc_file);
36 
37 	return is_gtk_theme;
38 }
39 
40 GList*
get_themes(void)41 get_themes (void)
42 {
43 	gchar *homedir;
44 	gchar *dirname;
45 	DIR *dir;
46 	struct dirent *dent;
47 	struct stat stats;
48 	gchar *origdir=g_get_current_dir(); /* back up cwd */
49 	GList *list=0;
50 	gchar *full_path;
51 
52 	homedir = (gchar*)getenv ("HOME");
53 	settings = gtk_settings_get_default ();
54 
55 	dirname = g_strconcat(homedir,"/.themes",NULL);
56 	chdir (dirname);
57 	dir = opendir (dirname);
58 	if (dir)
59 	{
60 		while ((dent = readdir (dir)))
61 		{
62 			stat(dent->d_name,&stats);
63 			if (!S_ISDIR(stats.st_mode)) continue;
64 			if (strcmp(dent->d_name,"." ) == 0) continue;
65 			if (strcmp(dent->d_name,"..") == 0) continue;
66 
67 			full_path = g_strconcat (homedir, "/.themes/", dent->d_name, NULL);
68 			if (!is_themedir (full_path))
69 			{
70 				g_free (full_path);
71 				continue;
72 			}
73 			list = g_list_insert_sorted(list, dent->d_name, (GCompareFunc)strcmp);
74 		}
75 	}
76 
77 	g_free (dirname);
78 
79 	dirname = (gchar*)gtk_rc_get_theme_dir();
80 	chdir (dirname);
81 	dir = opendir (dirname);
82 	if (dir)
83 	{
84 	        while ((dent = readdir (dir)))
85 	        {
86 			stat(dent->d_name,&stats);
87 			if (!S_ISDIR(stats.st_mode)) continue;
88 			if (strcmp(dent->d_name, "." ) == 0) continue;
89 			if (strcmp(dent->d_name, "..") == 0) continue;
90 
91 			full_path = g_strconcat (dirname, "/", dent->d_name, NULL);
92 			if (!is_themedir (full_path))
93 			{
94 				g_free (full_path);
95 				continue;
96 			}
97 			list = g_list_insert_sorted(list, dent->d_name, (GCompareFunc)strcmp);
98 	        }
99 	}
100 
101 	chdir (origdir); /* Go back to where we were */
102 	g_free (dirname);
103 	g_free (origdir);
104 
105 	return list;
106 }
107 
108 static void
select_theme(gpointer data,gpointer userdata)109 select_theme (gpointer data, gpointer userdata)
110 {
111 	GList       *children = gtk_container_get_children (GTK_CONTAINER (data));
112 	GtkWidget   *label    = g_list_first (children)->data;
113 	const gchar *theme    = gtk_label_get_label (GTK_LABEL (label));
114 
115 	gtk_settings_set_string_property (settings, "gtk-theme-name", theme, "gtkrc:0");
116 }
117 
118 static void
add_theme(gpointer data,gpointer user_data)119 add_theme (gpointer data, gpointer user_data)
120 {
121 	GtkWidget *menu = (GtkWidget*)user_data;
122 	GtkWidget *item = gtk_menu_item_new_with_label ((gchar*)data);
123 
124 	gtk_menu_append (menu, item);
125 	g_signal_connect (G_OBJECT (item), "activate", (GCallback)select_theme, NULL);
126 }
127 
128 void
create_themes_menu(GtkWidget * menuitem)129 create_themes_menu (GtkWidget *menuitem)
130 {
131 	GtkWidget *menu   = gtk_menu_new ();
132 	GList     *themes = get_themes ();
133 
134 	g_list_foreach (themes, add_theme, menu);
135 
136 	gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), menu);
137 	gtk_widget_show_all (menu);
138 }
139 
140 
141 
142