Little fixes for LXAppearance.
[lxde/lxappearance.git] / src / main-dlg.c
1 #ifdef HAVE_CONFIG_H
2 # include <config.h>
3 #endif
4
5 #include <gtk/gtk.h>
6 #include <gdk/gdkx.h>
7
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <unistd.h>
11
12 #include "main-dlg.h"
13 #include "main-dlg-ui.h"
14 #include "glade-support.h"
15
16 /* for kill & waitpid */
17 #include <sys/types.h>
18 #include <signal.h>
19 #include <sys/wait.h>
20
21 #define GET_WIDGET( name ) name = lookup_widget( dlg, #name )
22 #define INIT_LIST(name, prop) \
23 GET_WIDGET( name##_view ); \
24 name##_list = init_tree_view( name##_view, G_CALLBACK(on_list_sel_changed), prop ); \
25 load_##name##s( name##_list );
26
27 static GtkTreeView* gtk_theme_view = NULL;
28 static GtkListStore* gtk_theme_list = NULL;
29
30 static GtkTreeView* icon_theme_view = NULL;
31 static GtkListStore* icon_theme_list = NULL;
32
33 static char* gtk_theme_name = NULL;
34 static char* icon_theme_name = NULL;
35 static char* font_name = NULL;
36
37 static char tmp_rc_file[] = "/tmp/gtkrc-2.0-XXXXXX";
38 static char* rc_file = NULL;
39
40 /*
41 static GtkTreeView* font_view = NULL;
42 static GtkListStore* font_list = NULL;
43 */
44 static GtkWidget* demo_socket = NULL;
45 static GPid demo_pid = 0;
46
47 static void write_rc_file( const char* path )
48 {
49 FILE* f;
50 if( f = fopen( path, "w" ) )
51 {
52 fputs( "# DO NOT EDIT! This file will be overwritten by LXAppearance.\n"
53 "# Any customization should be done in ~/.gtkrc-2.0.mine\n\n", f );
54
55 fprintf( f, "gtk-theme-name=\"%s\"\n", gtk_theme_name );
56 fprintf( f, "gtk-icon-theme-name=\"%s\"\n", icon_theme_name );
57 fprintf( f, "gtk-font-name=\"%s\"\n", font_name );
58 fprintf( f, "include \"%s/.gtkrc-2.0.mine\"\n", g_get_home_dir() );
59
60 fclose( f );
61 }
62 }
63
64 static void reload_theme()
65 {
66
67 gtk_rc_reparse_all();
68 }
69
70 static void on_list_sel_changed( GtkTreeSelection* sel, const char* prop )
71 {
72 GtkTreeIter it;
73 GtkTreeModel* model;
74 if( gtk_tree_selection_get_selected( sel, &model, &it ) )
75 {
76 char* name;
77 gtk_tree_model_get( model, &it, 0, &name, -1 );
78
79 if( model == gtk_theme_list ) /* gtk+ theme */
80 {
81 if( name && gtk_theme_name && 0 == strcmp( name, gtk_theme_name ) )
82 goto out;
83 g_free( gtk_theme_name );
84 gtk_theme_name = name;
85 }
86 else if( model == icon_theme_list ) /* icon theme */
87 {
88 if( name && icon_theme_name && 0 == strcmp( name, icon_theme_name ) )
89 goto out;
90 g_free( icon_theme_name );
91 icon_theme_name = name;
92 }
93 write_rc_file( tmp_rc_file );
94 gtk_rc_reparse_all_for_settings(gtk_settings_get_default(), TRUE);
95 return;
96 out:
97 g_free( name );
98 }
99 }
100
101 static GtkListStore* init_tree_view( GtkTreeView* view, GCallback on_sel_changed, const char* prop )
102 {
103 GtkTreeViewColumn* col;
104 GtkListStore* list;
105 GtkTreeSelection* sel;
106 col = gtk_tree_view_column_new_with_attributes( NULL, gtk_cell_renderer_text_new(), "text", 0, NULL );
107 gtk_tree_view_append_column( view, col );
108 sel = gtk_tree_view_get_selection(view);
109 g_signal_connect( sel, "changed", on_sel_changed, prop );
110
111 list = gtk_list_store_new( 1, G_TYPE_STRING );
112 gtk_tree_view_set_model( view, (GtkTreeModel*)list );
113 g_object_unref( list );
114 return list;
115 }
116
117 static void load_themes_from_dir( GtkListStore* list,
118 const char* dir_path,
119 const char* lookup,
120 GtkTreeSelection* sel,
121 const char* init_sel )
122 {
123 GDir* dir;
124 if( dir = g_dir_open( dir_path, 0, NULL ) )
125 {
126 char* name;
127 while( name = g_dir_read_name( dir ) )
128 {
129 char* file = g_build_filename( dir_path, name, lookup, NULL );
130 if( g_file_test( file, G_FILE_TEST_EXISTS ) )
131 {
132 GtkTreeIter it;
133 gtk_list_store_append( list, &it );
134 gtk_list_store_set( list, &it, 0, name, -1 );
135 if( 0 == strcmp( name, init_sel ) )
136 {
137 GtkTreeView* view;
138 GtkTreePath* tp;
139 gtk_tree_selection_select_iter( sel, &it );
140 view = gtk_tree_selection_get_tree_view( sel );
141 tp = gtk_tree_model_get_path( (GtkTreeModel*)list, &it );
142 gtk_tree_view_scroll_to_cell( view, tp, NULL, FALSE, 0, 0 );
143 gtk_tree_path_free( tp );
144 }
145 }
146 g_free( file );
147 }
148 g_dir_close( dir );
149 }
150 }
151
152 static void load_from_data_dirs( GtkListStore* list,
153 const char* relative_path,
154 const char* lookup,
155 GtkTreeSelection* sel,
156 const char* init_sel )
157 {
158 const char* const *dirs = g_get_system_data_dirs();
159 const char* const *dir;
160 char* dir_path;
161 for( dir = dirs; *dir; ++dir )
162 {
163 dir_path = g_build_filename( *dir, relative_path, NULL );
164 load_themes_from_dir( list, dir_path, lookup, sel, init_sel );
165 g_free( dir_path );
166 }
167 dir_path = g_build_filename( g_get_user_data_dir(), relative_path, NULL );
168 load_themes_from_dir( list, dir_path, lookup, sel, init_sel );
169 g_free( dir_path );
170 }
171
172 static void load_gtk_themes( GtkListStore* list )
173 {
174 GtkTreeSelection* sel = gtk_tree_view_get_selection( gtk_theme_view );
175 load_from_data_dirs( list, "themes", "gtk-2.0", sel, gtk_theme_name );
176 }
177
178 static void load_icon_themes( GtkListStore* list )
179 {
180 char* path;
181 GtkTreeSelection* sel = gtk_tree_view_get_selection( icon_theme_view );
182 load_from_data_dirs( list, "icons", "index.theme", sel, icon_theme_name );
183 path = g_build_filename( g_get_home_dir(), ".icons", NULL );
184 load_themes_from_dir( list, path, "index.theme", sel, icon_theme_name );
185 g_free( path );
186 }
187
188 /*
189 static void load_fonts( GtkListStore* list )
190 {
191
192 }
193 */
194
195 static void load_demo_process()
196 {
197 char* argv[]={ NULL, "demo", NULL, NULL };
198 char wid[16];
199
200 if( demo_pid > 0 ) /* kill old demo */
201 {
202
203 }
204 g_snprintf( wid, 16, "%ld", gtk_socket_get_id(demo_socket) );
205
206 argv[0] = g_get_prgname();
207 argv[2] = wid;
208 g_spawn_async(NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, &demo_pid, NULL );
209 }
210
211 void main_dlg_init( GtkWidget* dlg )
212 {
213 GtkWidget* demo_box;
214 char* files[] = { tmp_rc_file, NULL };
215 char** def_files = gtk_rc_get_default_files();
216 char** file;
217
218 for( file = def_files; *file; ++file )
219 {
220 if( 0 == access( *file, W_OK ) )
221 rc_file = *file;
222 }
223 if( rc_file )
224 rc_file = g_strdup( rc_file );
225 else
226 rc_file = g_build_filename( g_get_home_dir(), ".gtkrc-2.0", NULL );
227 mkstemp( tmp_rc_file );
228
229 g_object_get( gtk_settings_get_default(), "gtk-theme-name", &gtk_theme_name, NULL );
230 if( ! gtk_theme_name )
231 gtk_theme_name = g_strdup( "Raleigh" );
232 g_object_get( gtk_settings_get_default(), "gtk-icon-theme-name", &icon_theme_name, NULL );
233 if( ! icon_theme_name )
234 gtk_theme_name = g_strdup( "hicolor" );
235 g_object_get( gtk_settings_get_default(), "gtk-font-name", &font_name, NULL );
236 if( ! font_name )
237 font_name = g_strdup( "Sans 10" );
238
239 gtk_rc_set_default_files( files );
240 write_rc_file( tmp_rc_file );
241 gtk_rc_reparse_all();
242
243 INIT_LIST( gtk_theme, "gtk-theme-name" )
244 INIT_LIST( icon_theme, "gtk-icon-theme-name" )
245 gtk_font_button_set_font_name( (GtkFontButton*)lookup_widget(dlg, "font"), font_name );
246
247 /* INIT_LIST( font, "gtk-font-name" ) */
248 /*
249 GET_WIDGET( demo_box );
250 demo_socket = gtk_socket_new();
251 gtk_widget_show( demo_socket );
252 gtk_widget_show( demo_box );
253 gtk_widget_set_app_paintable( demo_socket, TRUE );
254 gtk_container_add( (GtkContainer*)demo_box, demo_socket );
255 gtk_widget_realize( dlg );
256 load_demo_process();
257 */
258 }
259
260 static void reload_all_programs( gboolean icon_only )
261 {
262 GdkEventClient event;
263 event.type = GDK_CLIENT_EVENT;
264 event.send_event = TRUE;
265 event.window = NULL;
266
267 if( icon_only )
268 event.message_type = gdk_atom_intern("_GTK_LOAD_ICONTHEMES", FALSE);
269 else
270 event.message_type = gdk_atom_intern("_GTK_READ_RCFILES", FALSE);
271
272 event.data_format = 8;
273 gdk_event_send_clientmessage_toall((GdkEvent *)&event);
274 }
275
276 void
277 on_apply_clicked (GtkButton *button,
278 gpointer user_data)
279 {
280 write_rc_file( rc_file );
281 reload_all_programs( FALSE );
282 }
283
284
285 void
286 on_font_changed (GtkFontButton *fontbutton,
287 gpointer user_data)
288 {
289 const char* name = gtk_font_button_get_font_name(fontbutton);
290 if( name && font_name && 0 == strcmp( font_name ) )
291 return;
292 g_free( font_name );
293 font_name = g_strdup( name );
294 write_rc_file( tmp_rc_file );
295 gtk_rc_reparse_all_for_settings( gtk_settings_get_default(), TRUE );
296 }
297