4828ac7a3febe8ec8581c52727c12e3d43e3b208
[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 #include <glib/gi18n.h>
8
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <unistd.h>
12 #include <string.h>
13
14 /* for kill & waitpid */
15 #include <sys/types.h>
16 #include <signal.h>
17 #include <sys/wait.h>
18
19 #include "main-dlg.h"
20
21 enum {
22 COL_DISP_NAME,
23 COL_NAME,
24 N_COLS
25 };
26
27 #define LOOKUP(name) gtk_builder_get_object( builder, #name )
28 #define GET_WIDGET_WITH_TYPE(name, type) name = type(LOOKUP(name))
29
30 #define INIT_LIST(name, prop) \
31 GET_WIDGET_WITH_TYPE( name##_view, GTK_TREE_VIEW ); \
32 name##_list = init_tree_view( name##_view, G_CALLBACK(on_list_sel_changed), prop); \
33 load_##name##s( name##_list, name##_name );
34
35 #define enable_apply() gtk_dialog_set_response_sensitive(GTK_DIALOG (main_dlg), GTK_RESPONSE_APPLY, TRUE )
36 #define disable_apply() gtk_dialog_set_response_sensitive(GTK_DIALOG (main_dlg), GTK_RESPONSE_APPLY, FALSE )
37
38 extern gboolean under_lxsession; /* wether we are under lxsession */
39
40 extern GtkWidget* main_dlg; /* defined in main.c */
41
42 static GtkTreeView* gtk_theme_view = NULL;
43 static GtkListStore* gtk_theme_list = NULL;
44
45 static GtkTreeView* icon_theme_view = NULL;
46 static GtkListStore* icon_theme_list = NULL;
47
48 #if CURSOR_THEME
49 static GtkTreeView* cursor_theme_view = NULL;
50 static GtkListStore* cursor_theme_list = NULL;
51 #endif
52
53 static char* gtk_theme_name = NULL;
54 static char* icon_theme_name = NULL;
55 static char* font_name = NULL;
56 static char* cursor_theme_name = NULL;
57 static gint cursor_theme_size = 0;
58 static GtkToolbarStyle tb_style = GTK_TOOLBAR_BOTH;
59
60 extern char tmp_rc_file[];
61 static char* rc_file = NULL;
62
63 /*
64 static GtkTreeView* font_view = NULL;
65 static GtkListStore* font_list = NULL;
66 */
67 static GtkWidget* demo_box = NULL;
68 static GtkWidget* demo_socket = NULL;
69 static GPid demo_pid = 0;
70
71 static const char* session_name = NULL;
72
73 extern Atom lxsession_atom; /* defined in main.c */
74
75 static void reload_demo_process()
76 {
77 char* argv[5];
78 char wid[16];
79
80 if( demo_pid > 0 ) /* kill old demo */
81 {
82 int stat;
83 kill( demo_pid, SIGTERM );
84 waitpid( demo_pid, &stat, 0 );
85 demo_pid = 0;
86 }
87
88 g_snprintf( wid, 16, "%ld", gtk_socket_get_id(GTK_SOCKET (demo_socket)) );
89
90 argv[0] = g_get_prgname();
91 argv[1] = "demo";
92 argv[2] = wid;
93 argv[3] = tmp_rc_file;
94 argv[4] = NULL;
95 g_spawn_async(NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, &demo_pid, NULL );
96
97 /* reloading demo means the current selected theme is changed */
98 enable_apply();
99 }
100
101 static void write_rc_file( const char* path )
102 {
103 FILE* f;
104 static char* tb_styles[] = {
105 "GTK_TOOLBAR_ICONS",
106 "GTK_TOOLBAR_TEXT",
107 "GTK_TOOLBAR_BOTH",
108 "GTK_TOOLBAR_BOTH_HORIZ"
109 };
110
111 if( f = fopen( path, "w" ) )
112 {
113 fputs( "# DO NOT EDIT! This file will be overwritten by LXAppearance.\n"
114 "# Any customization should be done in ~/.gtkrc-2.0.mine\n\n", f );
115
116 fprintf( f, "gtk-theme-name=\"%s\"\n", gtk_theme_name );
117 fprintf( f, "gtk-icon-theme-name=\"%s\"\n", icon_theme_name );
118 fprintf( f, "gtk-font-name=\"%s\"\n", font_name );
119 fprintf( f, "gtk-toolbar-style=%d\n", tb_style );
120 #if CURSOR_THEME
121 fprintf( f, "gtk-cursor-theme-name=\"%s\"\n", cursor_theme_name );
122 fprintf( f, "gtk-cursor-theme-size=%d\n", cursor_theme_size );
123 #endif
124
125 fprintf( f, "include \"%s/.gtkrc-2.0.mine\"\n", g_get_home_dir() );
126
127 fclose( f );
128 }
129 }
130
131 static void create_lxsession_config_dir()
132 {
133 char* dir = g_build_filename( g_get_user_config_dir(), "lxsession", session_name, NULL );
134 g_mkdir_with_parents( dir, 0755 );
135 g_free( dir );
136 }
137
138 static void write_lxsession_config()
139 {
140 FILE* f;
141 char* file, *data;
142 gsize len;
143 GKeyFile* kf = g_key_file_new();
144 gboolean ret;
145
146 file = g_build_filename( g_get_user_config_dir(), "lxsession", session_name, "desktop.conf", NULL );
147 ret = g_key_file_load_from_file( kf, file, G_KEY_FILE_KEEP_COMMENTS, NULL );
148
149 if( ! ret )
150 {
151 const gchar* const * dir;
152 const gchar* const * dirs = g_get_system_config_dirs();
153 create_lxsession_config_dir();
154
155 /* load system-wide config file */
156 for( dir = dirs; *dir; ++dir )
157 {
158 char* path = g_build_filename( *dir, "lxsession", session_name, "desktop.conf", NULL );
159 ret = g_key_file_load_from_file( kf, path, G_KEY_FILE_KEEP_COMMENTS, NULL );
160 g_free( path );
161 if( ret )
162 break;
163 }
164 }
165
166 g_key_file_set_string( kf, "GTK", "sNet/ThemeName", gtk_theme_name );
167 g_key_file_set_string( kf, "GTK", "sNet/IconThemeName", icon_theme_name );
168 g_key_file_set_string( kf, "GTK", "sGtk/FontName", font_name );
169 g_key_file_set_integer( kf, "GTK", "iGtk/ToolbarStyle", tb_style );
170 #if CURSOR_THEME
171 g_key_file_set_string( kf, "GTK", "sGtk/CursorThemeName", cursor_theme_name );
172 g_key_file_set_integer( kf, "GTK", "iGtk/CursorThemeSize", cursor_theme_size );
173 #endif
174
175 data = g_key_file_to_data( kf, &len, NULL );
176 g_key_file_free( kf );
177
178 if( f = fopen( file, "w" ) )
179 {
180 fwrite( data, sizeof(char), len, f );
181 fclose( f );
182 }
183 g_free( data );
184 }
185
186 static void reload_theme()
187 {
188
189 gtk_rc_reparse_all();
190 }
191
192 static void on_list_sel_changed( GtkTreeSelection* sel, const char* prop )
193 {
194 GtkTreeIter it;
195 GtkTreeModel* model;
196 if( gtk_tree_selection_get_selected( sel, &model, &it ) )
197 {
198 char* name;
199 gtk_tree_model_get( model, &it, COL_NAME, &name, -1 );
200
201 if( model == GTK_TREE_MODEL (gtk_theme_list) ) /* gtk+ theme */
202 {
203 if( name && gtk_theme_name && 0 == strcmp( name, gtk_theme_name ) )
204 goto out;
205 g_free( gtk_theme_name );
206 gtk_theme_name = name;
207
208 if( under_lxsession )
209 g_object_set( gtk_settings_get_default(), "gtk-theme-name", name, NULL );
210 }
211 else if( model == GTK_TREE_MODEL (icon_theme_list) ) /* icon theme */
212 {
213 if( name && icon_theme_name && 0 == strcmp( name, icon_theme_name ) )
214 goto out;
215 g_free( icon_theme_name );
216 icon_theme_name = name;
217
218 if( under_lxsession )
219 g_object_set( gtk_settings_get_default(), "gtk-icon-theme-name", name, NULL );
220 }
221 #if CURSOR_THEME
222 else if( model == GTK_TREE_MODEL (cursor_theme_list) ) /* cursor theme */
223 {
224 if( name && cursor_theme_name && 0 == strcmp( name, cursor_theme_name ) )
225 goto out;
226 g_free( cursor_theme_name );
227 cursor_theme_name = g_strdup(name);
228 //gdk_x11_display_set_cursor_theme ( gdk_display_get_default (), name, cursor_theme_size );
229
230 if( under_lxsession )
231 g_object_set( gtk_settings_get_default(), "gtk-cursor-theme-name", name, NULL );
232 }
233 #endif
234
235 if( under_lxsession )
236 {
237 enable_apply();
238 }
239 else
240 {
241 write_rc_file( tmp_rc_file );
242 //gtk_rc_reparse_all_for_settings(gtk_settings_get_default(), TRUE);
243 reload_demo_process();
244 }
245 return;
246 out:
247 g_free( name );
248 }
249 }
250
251 static gint sort_func( GtkTreeModel* model, GtkTreeIter* it1, GtkTreeIter* it2, gpointer data )
252 {
253 char* str1, *str2;
254 int ret;
255 gtk_tree_model_get( model, it1, COL_DISP_NAME, &str1, -1 );
256 gtk_tree_model_get( model, it2, COL_DISP_NAME, &str2, -1 );
257 ret = g_utf8_collate( str1, str2 );
258 g_free( str1 );
259 g_free( str2 );
260 return ret;
261 }
262
263 static GtkListStore* init_tree_view( GtkTreeView* view, GCallback on_sel_changed, const char* prop )
264 {
265 GtkTreeViewColumn* col;
266 GtkListStore* list;
267 GtkTreeSelection* sel;
268 int text_col = strcmp(prop, "gtk-theme-name") && strcmp(prop, "gtk-cursor-theme-name") ? COL_DISP_NAME : COL_NAME;
269
270 col = gtk_tree_view_column_new_with_attributes( NULL, gtk_cell_renderer_text_new(),
271 "text", text_col, NULL );
272 gtk_tree_view_append_column( view, col );
273
274 sel = gtk_tree_view_get_selection(view);
275 g_signal_connect( sel, "changed", on_sel_changed, GINT_TO_POINTER(prop) );
276
277 list = gtk_list_store_new( N_COLS, G_TYPE_STRING, G_TYPE_STRING );
278 gtk_tree_sortable_set_sort_func( (GtkTreeSortable*)list, text_col, sort_func, NULL, NULL );
279 gtk_tree_view_set_model( view, (GtkTreeModel*)list );
280 g_object_unref( list );
281 return list;
282 }
283
284 typedef gboolean (*ThemeFunc)(const char* file, const char* dir, const char* name, GtkListStore* list, GtkTreeIter* it);
285
286 static void load_themes_from_dir( GtkListStore* list,
287 const char* dir_path,
288 const char* lookup,
289 GtkTreeSelection* sel,
290 const char* init_sel,
291 ThemeFunc theme_func )
292 {
293 GDir* dir;
294 if( dir = g_dir_open( dir_path, 0, NULL ) )
295 {
296 const char* name;
297 while( name = g_dir_read_name( dir ) )
298 {
299 char* file = g_build_filename( dir_path, name, lookup, NULL );
300 if( g_file_test( file, G_FILE_TEST_EXISTS ) )
301 {
302 gboolean add = TRUE;
303 GtkTreeIter it;
304
305 /* prevent duplication */
306 if( gtk_tree_model_get_iter_first(GTK_TREE_MODEL (list), &it ) )
307 {
308 char* _name;
309 do {
310 _name = NULL;
311 gtk_tree_model_get(GTK_TREE_MODEL (list), &it, COL_NAME, &_name, -1);
312 if( _name && strcmp(_name, name) == 0 )
313 {
314 add = FALSE;
315 g_free(_name);
316 break;
317 }
318 g_free(_name);
319 }
320 while( gtk_tree_model_iter_next(GTK_TREE_MODEL (list), &it ) );
321 }
322
323 if( add )
324 {
325 gtk_list_store_append( list, &it );
326 gtk_list_store_set( list, &it, COL_NAME, name, -1 );
327
328 if( theme_func )
329 {
330 if( ! theme_func(file, (char *) dir, name, list, &it) )
331 add = FALSE;
332 }
333
334 if( add )
335 {
336 if( 0 == strcmp( name, init_sel ) )
337 {
338 GtkTreeView* view;
339 GtkTreePath* tp;
340 gtk_tree_selection_select_iter( sel, &it );
341 view = gtk_tree_selection_get_tree_view( sel );
342 tp = gtk_tree_model_get_path( (GtkTreeModel*)list, &it );
343 gtk_tree_view_scroll_to_cell( view, tp, NULL, FALSE, 0, 0 );
344 gtk_tree_path_free( tp );
345 }
346 }
347 else
348 gtk_list_store_remove( list, &it );
349 }
350 }
351 g_free( file );
352 }
353 g_dir_close( dir );
354 }
355 }
356
357 static void load_from_data_dirs( GtkListStore* list,
358 const char* relative_path,
359 const char* lookup,
360 GtkTreeSelection* sel,
361 const char* init_sel,
362 ThemeFunc theme_func )
363 {
364 const char* const *dirs = g_get_system_data_dirs();
365 const char* const *dir;
366 char* dir_path;
367 for( dir = dirs; *dir; ++dir )
368 {
369 dir_path = g_build_filename( *dir, relative_path, NULL );
370 load_themes_from_dir( list, dir_path, lookup, sel, init_sel, theme_func );
371 g_free( dir_path );
372 }
373 dir_path = g_build_filename( g_get_user_data_dir(), relative_path, NULL );
374 load_themes_from_dir( list, dir_path, lookup, sel, init_sel, theme_func );
375 g_free( dir_path );
376 }
377
378 static gboolean icon_theme_func(const char* file, const char* dir, const char* name, GtkListStore* list, GtkTreeIter* it)
379 {
380 GKeyFile* kf;
381 char* disp_name = NULL;
382 if( g_str_has_prefix( name, "default." ) )
383 return FALSE;
384
385 kf = g_key_file_new();
386 if( g_key_file_load_from_file(kf, file, 0, NULL) )
387 {
388 if( g_key_file_has_key(kf, "Icon Theme", "Directories", NULL)
389 && ! g_key_file_get_boolean(kf, "Icon Theme", "Hidden", NULL) )
390 {
391 disp_name = g_key_file_get_locale_string(kf, "Icon Theme", "Name", NULL, NULL);
392 gtk_list_store_set( list, it, COL_DISP_NAME, disp_name ? disp_name : name, -1 );
393 }
394 }
395 g_key_file_free(kf);
396 return disp_name != NULL;
397 }
398
399 #if CURSOR_THEME
400 static gboolean cursor_theme_func(const char* dir, const char* name, const char* lookup)
401 {
402 char* ret = NULL;
403 /*
404 GKeyFile* kf = g_key_file_new();
405 if( g_key_file_load_from_file(kf, lookup, 0, NULL) )
406 {
407 if( g_key_file_has_key(kf, "Icon Theme", "Directories", NULL) )
408 {
409 ret = g_key_file_get_locale_string(kf, "Icon Theme", "Name", NULL, NULL);
410 }
411 }
412 g_key_file_free(kf);
413 */
414 return ret != NULL;
415 }
416 #endif
417
418 static void load_gtk_themes( GtkListStore* list, const char* cur_sel )
419 {
420 char* path;
421 GtkTreeSelection* sel = gtk_tree_view_get_selection( gtk_theme_view );
422 load_from_data_dirs( list, "themes", "gtk-2.0", sel, cur_sel, NULL );
423 path = g_build_filename( g_get_home_dir(), ".themes", NULL );
424 load_themes_from_dir( list, path, "gtk-2.0", sel, cur_sel, NULL );
425 g_free( path );
426 gtk_tree_sortable_set_sort_column_id( (GtkTreeSortable*)list, 0, GTK_SORT_ASCENDING );
427 }
428
429 static void load_icon_themes( GtkListStore* list, const char* cur_sel )
430 {
431 char* path;
432 GtkTreeSelection* sel = gtk_tree_view_get_selection( icon_theme_view );
433 load_from_data_dirs( list, "icons", "index.theme", sel, cur_sel, icon_theme_func );
434 path = g_build_filename( g_get_home_dir(), ".icons", NULL );
435 load_themes_from_dir( list, path, "index.theme", sel, cur_sel, icon_theme_func );
436 g_free( path );
437 gtk_tree_sortable_set_sort_column_id( (GtkTreeSortable*)list, 0, GTK_SORT_ASCENDING );
438 }
439
440 #if CURSOR_THEME
441 static void load_cursor_themes( GtkListStore* list, const char* cur_sel )
442 {
443 char* path;
444 GtkTreeSelection* sel = gtk_tree_view_get_selection( cursor_theme_view );
445 load_from_data_dirs( list, "icons", "cursors", sel, cur_sel, NULL );
446 path = g_build_filename( g_get_home_dir(), ".icons", NULL );
447 load_themes_from_dir( list, path, "cursors", sel, cur_sel, NULL );
448 g_free( path );
449 gtk_tree_sortable_set_sort_column_id( (GtkTreeSortable*)list, 0, GTK_SORT_ASCENDING );
450 }
451 #endif
452
453 /*
454 static void load_fonts( GtkListStore* list )
455 {
456
457 }
458 */
459
460 gboolean center_win( GtkWidget* dlg )
461 {
462 gtk_widget_show( dlg );
463 return FALSE;
464 }
465
466 static void on_demo_loaded( GtkSocket* socket, GtkWidget* dlg )
467 {
468 /* sleep for 0.8 sec for loading of the demo window */
469 /* FIXME: we need a better way to do this, such as IPC */
470 g_timeout_add_full( G_PRIORITY_LOW, 800, (GSourceFunc)center_win, dlg, NULL );
471 g_signal_handlers_disconnect_by_func( socket, on_demo_loaded, dlg );
472 }
473
474 GtkWidget* main_dlg_new()
475 {
476 GtkBuilder* builder = gtk_builder_new();
477 GtkWidget* dlg;
478 char* files[] = { tmp_rc_file, NULL };
479 char** def_files = gtk_rc_get_default_files();
480 char** file;
481
482 if( under_lxsession )
483 {
484 session_name = g_getenv("DESKTOP_SESSION");
485 }
486 else
487 {
488 /* no lxsession-settings daemon, use gtkrc-2.0 */
489 for( file = def_files; *file; ++file )
490 {
491 if( 0 == access( *file, W_OK ) )
492 rc_file = *file;
493 }
494 if( rc_file )
495 rc_file = g_strdup( rc_file );
496 else
497 rc_file = g_build_filename( g_get_home_dir(), ".gtkrc-2.0", NULL );
498 }
499 g_object_get( gtk_settings_get_default(),
500 "gtk-theme-name", &gtk_theme_name,
501 "gtk-icon-theme-name", &icon_theme_name,
502 "gtk-font-name", &font_name,
503 "gtk-toolbar-style", &tb_style,
504 #if CURSOR_THEME
505 "gtk-cursor-theme-name", &cursor_theme_name,
506 "gtk-cursor-theme-size", &cursor_theme_size,
507 #endif
508 NULL );
509
510 if( ! gtk_theme_name )
511 gtk_theme_name = g_strdup( "Raleigh" );
512 if( ! icon_theme_name )
513 icon_theme_name = g_strdup( "hicolor" );
514 #if CURSOR_THEME
515 if( ! cursor_theme_name )
516 cursor_theme_name = g_strdup( "default" );
517 #endif
518 if( ! font_name )
519 font_name = g_strdup( "Sans 10" );
520 if( ! cursor_theme_size )
521 cursor_theme_size = 16;
522
523 /* no lxsession-settings daemon, use gtkrc-2.0 */
524 if( ! under_lxsession )
525 write_rc_file( tmp_rc_file );
526
527 gtk_builder_add_from_file(builder, PACKAGE_DATA_DIR "/lxappearance/lxappearance.ui", NULL);
528 gtk_builder_connect_signals(builder, NULL);
529
530 GET_WIDGET_WITH_TYPE(dlg, GTK_WIDGET);
531 main_dlg = dlg;
532
533 INIT_LIST( gtk_theme, "gtk-theme-name" )
534 INIT_LIST( icon_theme, "gtk-icon-theme-name" )
535
536 #if CURSOR_THEME
537 INIT_LIST( cursor_theme, "gtk-cursor-theme-name" )
538 #endif
539
540 gtk_font_button_set_font_name( (GtkFontButton*)LOOKUP(font), font_name );
541
542 #if CURSOR_THEME
543 gtk_range_set_value( GTK_RANGE(LOOKUP(cursor_theme_size)), cursor_theme_size );
544 #endif
545
546 gtk_combo_box_set_active( GTK_COMBO_BOX(LOOKUP(tb_style)), tb_style < 4 ? tb_style : 3 );
547
548 GET_WIDGET_WITH_TYPE( demo_box, GTK_WIDGET );
549 gtk_widget_show( demo_box );
550
551 if( under_lxsession )
552 {
553 /* XSettings daemon of lxsession is running, gtkrc is useless.
554 * We should set properties of GtkSettings object on the fly.
555 * This will cause problems with some themes, but we have no choice.
556 */
557 show_demo( (GdkNativeWindow)demo_box );
558 gtk_widget_show( dlg );
559 }
560 else
561 {
562 /* no lxsession-settings daemon, use gtkrc-2.0 and load preview in another process */
563 demo_socket = gtk_socket_new();
564 g_signal_connect( demo_socket, "plug-added", G_CALLBACK(on_demo_loaded), dlg );
565 g_signal_connect( demo_socket, "plug-removed", G_CALLBACK(gtk_true), NULL );
566 gtk_widget_show( demo_socket );
567 gtk_container_add( (GtkContainer*)demo_box, demo_socket );
568
569 gtk_widget_realize( dlg );
570 reload_demo_process();
571 }
572
573 disable_apply();
574 return dlg;
575 }
576
577 static void reload_all_programs( gboolean icon_only )
578 {
579 GdkEventClient event;
580 event.type = GDK_CLIENT_EVENT;
581 event.send_event = TRUE;
582 event.window = NULL;
583
584 if( under_lxsession )
585 {
586 /*
587 char* argv[]={"lxsession", "-r", NULL};
588 g_spawn_sync(NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, NULL, NULL, NULL);
589 return;
590 */
591 event.message_type = gdk_atom_intern_static_string("_LXSESSION");
592 event.data.b[0] = 0; /* LXS_RELOAD */
593 }
594 else
595 {
596 if( icon_only )
597 event.message_type = gdk_atom_intern("_GTK_LOAD_ICONTHEMES", FALSE);
598 else
599 event.message_type = gdk_atom_intern("_GTK_READ_RCFILES", FALSE);
600 }
601 event.data_format = 8;
602 gdk_event_send_clientmessage_toall((GdkEvent *)&event);
603 }
604
605 void
606 on_apply_clicked (GtkButton *button,
607 gpointer user_data)
608 {
609 if( under_lxsession )
610 write_lxsession_config();
611 else
612 write_rc_file( rc_file );
613
614 reload_all_programs( FALSE );
615 disable_apply();
616 }
617
618
619 void
620 on_font_changed (GtkFontButton *fontbutton,
621 gpointer user_data)
622 {
623 const char* name = gtk_font_button_get_font_name(fontbutton);
624 if( name && font_name && 0 == strcmp( name, font_name ) )
625 return;
626 g_free( font_name );
627 font_name = g_strdup( name );
628
629 if( under_lxsession )
630 {
631 g_object_set( gtk_settings_get_default(), "gtk-font-name", font_name, NULL );
632
633 enable_apply();
634 }
635 else
636 {
637 write_rc_file( tmp_rc_file );
638 reload_demo_process();
639 }
640 }
641
642 void
643 on_install_theme_clicked (GtkButton *button,
644 gpointer user_data)
645 {
646 GtkFileFilter* filter = gtk_file_filter_new();
647 GtkWidget* fc = gtk_file_chooser_dialog_new( _("Select an icon theme"), NULL,
648 GTK_FILE_CHOOSER_ACTION_OPEN,
649 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
650 GTK_STOCK_OPEN, GTK_RESPONSE_OK, NULL );
651
652 gtk_file_filter_add_pattern( filter, "*.tar.gz" );
653 gtk_file_filter_add_pattern( filter, "*.tar.bz2" );
654 gtk_file_filter_set_name( filter, _("*.tar.gz, *.tar.bz2 (Icon Theme)") );
655
656 gtk_file_chooser_add_filter( GTK_FILE_CHOOSER(fc), filter );
657 gtk_file_chooser_set_filter( GTK_FILE_CHOOSER(fc), filter );
658
659 if( gtk_dialog_run( (GtkDialog*)fc ) == GTK_RESPONSE_OK )
660 {
661 char* file = gtk_file_chooser_get_filename( GTK_FILE_CHOOSER(fc) );
662 char* argv[]={
663 PACKAGE_DATA_DIR"/lxappearance/install-icon-theme.sh",
664 file, NULL };
665 int status = 0;
666 char* stdo = NULL;
667 if( g_spawn_sync( NULL, argv, NULL, 0, NULL, NULL, &stdo, NULL, &status, NULL ) && 0 == status )
668 {
669 char* sep = stdo ? strchr( stdo, '\n' ) : NULL;
670 if( sep )
671 *sep = '\0';
672
673 /* reload all icon themes */
674 gtk_list_store_clear( icon_theme_list );
675 load_icon_themes( icon_theme_list, stdo ? stdo : "" );
676
677 #if CURSOR_THEME
678 /* reload all cursor themes */
679 gtk_list_store_clear( cursor_theme_list );
680 load_cursor_themes( cursor_theme_list, stdo ? stdo : "" );
681 #endif
682 }
683 g_free( file );
684 }
685
686 gtk_widget_destroy( fc );
687 }
688
689
690 void
691 on_remove_theme_clicked (GtkButton *button,
692 gpointer user_data)
693 {
694
695 }
696
697 #if CURSOR_THEME
698 void
699 on_cursor_size_changed (GtkHScale *cursorsizescale,
700 gpointer user_data)
701 {
702 cursor_theme_size = gtk_range_get_value( GTK_RANGE(cursorsizescale) );
703
704 if( under_lxsession )
705 {
706 g_object_set( gtk_settings_get_default(), "gtk-cursor-theme-size", cursor_theme_size, NULL );
707 enable_apply();
708 }
709 else
710 {
711 write_rc_file( tmp_rc_file );
712 reload_demo_process();
713 }
714 }
715 #endif
716
717 void
718 on_tb_style_changed (GtkComboBox *combobox,
719 gpointer user_data)
720 {
721 int sel = gtk_combo_box_get_active( combobox );
722 if( sel == tb_style || sel < 0 )
723 return;
724 tb_style = sel;
725
726 if( under_lxsession )
727 {
728 g_object_set( gtk_settings_get_default(), "gtk-toolbar-style", tb_style, NULL );
729 enable_apply();
730 }
731 else
732 {
733 write_rc_file( tmp_rc_file );
734 reload_demo_process();
735 }
736 }
737