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