Use PtkUIXml and glade file to build a better config dialog.
[lxde/lxpanel.git] / src / configurator.c
CommitLineData
16fb8c2e 1/**
a99ee9e1
JH
2 * Copyright (c) 2006 LxDE Developers, see the file AUTHORS for details.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 */
18
a52c2257
HJYP
19#ifdef HAVE_CONFIG_H
20#include "config.h"
21#endif
22
23#include "plugin.h"
24#include "panel.h"
25#include "misc.h"
26#include "bg.h"
a52c2257
HJYP
27#include <stdlib.h>
28#include <sys/types.h>
29#include <sys/stat.h>
30#include <unistd.h>
31#include <string.h>
e7cb732b 32#include <glib/gi18n.h>
a52c2257 33
a52c2257
HJYP
34#include "dbg.h"
35
4b93d81e
HJYP
36#include "ptk-ui-xml.h"
37
38void panel_configure(Panel* p, int sel_page );
a52c2257 39void restart(void);
08ea5341 40void gtk_run(void);
cf701cb7 41void panel_config_save(Panel* panel);
389975e0 42static void logout(void);
a52c2257 43
22242ed4 44Command commands[] = {
8110399f 45 //{ "configure", N_("Preferences"), configure },
08ea5341
HJYP
46 { "run", N_("Run"), gtk_run },
47 { "restart", N_("Restart"), restart },
389975e0 48 { "logout", N_("Logout"), logout },
a52c2257
HJYP
49 { NULL, NULL },
50};
51
cf701cb7
HJYP
52static char* file_manager_cmd = NULL;
53static char* terminal_cmd = NULL;
54static char* logout_cmd = NULL;
55
8110399f 56extern GSList* all_panels;
a52c2257
HJYP
57extern gchar *cprofile;
58extern int config;
a52c2257 59
cf701cb7
HJYP
60void panel_global_config_save( Panel* p, FILE *fp);
61void panel_plugin_config_save( Panel* p, FILE *fp);
a52c2257 62
bee4c26e
HJYP
63static void update_opt_menu(GtkWidget *w, int ind);
64static void update_toggle_button(GtkWidget *w, gboolean n);
389975e0 65static void modify_plugin( GtkTreeView* view );
239cb032 66static void on_entry_changed( GtkEditable* edit, gpointer user_data );
bee4c26e 67
24053345
HJYP
68/* older versions of glib don't provde these API */
69#if ! GLIB_CHECK_VERSION(2, 8, 0)
70#include <errno.h>
71
72int g_mkdir_with_parents(const gchar *pathname, int mode)
a52c2257 73{
24053345
HJYP
74 struct stat statbuf;
75 char *dir, *sep;
76 dir = g_strdup( pathname );
77 sep = dir[0] == '/' ? dir + 1 : dir;
78 do {
79 sep = strchr( sep, '/' );
80 if( G_LIKELY( sep ) )
81 *sep = '\0';
82
83 if( stat( dir, &statbuf) == 0 )
84 {
85 if( ! S_ISDIR(statbuf.st_mode) ) /* parent not dir */
86 goto err;
87 }
88 else /* stat failed */
89 {
90 if( errno == ENOENT ) /* not exists */
91 {
92 if( mkdir( dir, mode ) == -1 )
93 goto err;
94 }
95 else
96 goto err; /* unknown error */
97 }
a52c2257 98
24053345
HJYP
99 if( G_LIKELY( sep ) )
100 {
101 *sep = '/';
102 ++sep;
103 }
104 else
105 break;
106 }while( sep );
107 g_free( dir );
108 return 0;
109err:
110 g_free( dir );
111 return -1;
a52c2257 112}
24053345 113#endif
a52c2257
HJYP
114
115static void
4b93d81e 116response_event(GtkDialog *widget, gint arg1, Panel* panel )
a52c2257 117{
a52c2257 118 switch (arg1) {
bee4c26e
HJYP
119 /* FIXME: what will happen if the user exit lxpanel without
120 close this config dialog?
121 Then the config won't be save, I guess. */
da76d5cf
HJYP
122 case GTK_RESPONSE_DELETE_EVENT:
123 case GTK_RESPONSE_CLOSE:
124 case GTK_RESPONSE_NONE:
cf701cb7 125 panel_config_save( panel );
9c97f69e 126 /* NOTE: NO BREAK HERE*/
4b93d81e 127 gtk_widget_destroy(widget);
a52c2257
HJYP
128 break;
129 }
4b93d81e 130 return;
a52c2257
HJYP
131}
132
133static void
8110399f 134update_panel_geometry( Panel* p )
bee4c26e
HJYP
135{
136 calculate_position(p);
137 gdk_window_move_resize(p->topgwin->window, p->ax, p->ay, p->aw, p->ah);
138
139 panel_set_wm_strut( p );
140}
141
142static void
8110399f 143set_edge( GtkComboBox *widget, Panel* p )
a52c2257
HJYP
144{
145 int edge;
04883e73
HJYP
146
147 ENTER;
a52c2257 148 edge = gtk_combo_box_get_active(widget) + 1;
bee4c26e 149 p->edge = edge;
a97d06a6 150 panel_set_orientation( p );
8110399f 151 update_panel_geometry(p);
4542c20d 152 panel_update_background( p );
a52c2257
HJYP
153 RET();
154}
155
a52c2257 156static void
8110399f 157set_allign( GtkComboBox *widget, Panel* p )
a52c2257
HJYP
158{
159 int allign;
160 gboolean t;
04883e73
HJYP
161
162 ENTER;
a52c2257 163 allign = gtk_combo_box_get_active(widget) + 1;
a52c2257 164 t = (allign != ALLIGN_CENTER);
4b93d81e 165 /*
a52c2257 166 gtk_widget_set_sensitive(margin_label, t);
04883e73 167 gtk_widget_set_sensitive(margin_spinb, t);
4b93d81e 168 */
bee4c26e 169 p->allign = allign;
8110399f 170 update_panel_geometry(p);
a52c2257
HJYP
171 RET();
172}
173
bee4c26e 174static void
8110399f 175set_margin( GtkSpinButton* spin, Panel* p )
bee4c26e
HJYP
176{
177 p->margin = (int)gtk_spin_button_get_value(spin);
8110399f 178 update_panel_geometry(p);
bee4c26e
HJYP
179}
180
bee4c26e 181static void
4b93d81e 182set_width( GtkSpinButton* spin, Panel* p )
bee4c26e
HJYP
183{
184 p->width = (int)gtk_spin_button_get_value(spin);
8110399f 185 update_panel_geometry(p);
bee4c26e 186}
a52c2257
HJYP
187
188static void
4b93d81e 189set_height( GtkSpinButton* spin, Panel* p )
bee4c26e
HJYP
190{
191 p->height = (int)gtk_spin_button_get_value(spin);
8110399f 192 update_panel_geometry(p);
bee4c26e
HJYP
193}
194
195static void
4b93d81e 196set_width_type( GtkWidget *item, Panel* p )
a52c2257 197{
4b93d81e 198 GtkWidget* spin;
a52c2257
HJYP
199 int widthtype;
200 gboolean t;
a52c2257 201 widthtype = gtk_combo_box_get_active(GTK_COMBO_BOX(item)) + 1;
bee4c26e 202 p->widthtype = widthtype;
4b93d81e
HJYP
203
204 spin = ptk_ui_xml_get_widget( gtk_widget_get_toplevel(item), "width" );
a52c2257 205 t = (widthtype != WIDTH_REQUEST);
4b93d81e 206 gtk_widget_set_sensitive( spin, t );
a52c2257 207 if (widthtype == WIDTH_PERCENT) {
4b93d81e
HJYP
208 gtk_spin_button_set_range( (GtkSpinButton*)spin, 0, 100 );
209 gtk_spin_button_set_value( (GtkSpinButton*)spin, 100 );
a52c2257 210 } else if (widthtype == WIDTH_PIXEL) {
4b93d81e
HJYP
211 gtk_spin_button_set_range( (GtkSpinButton*)spin, 0, gdk_screen_width() );
212 gtk_spin_button_set_value( (GtkSpinButton*)spin, gdk_screen_width() );
a52c2257 213 } else
4b93d81e 214 return;
04883e73 215
8110399f 216 update_panel_geometry(p);
a52c2257
HJYP
217}
218
219static void
8110399f 220transparency_toggle( GtkWidget *b, Panel* p)
a52c2257
HJYP
221{
222 gboolean t;
223
224 ENTER;
225 t = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b));
4b93d81e 226/*
a52c2257
HJYP
227 gtk_widget_set_sensitive(tr_colorl, t);
228 gtk_widget_set_sensitive(tr_colorb, t);
4b93d81e 229*/
be933927 230 /* Update background immediately. */
6576fd40
FC
231 if (t&&!p->transparent) {
232 p->transparent = 1;
4542c20d 233 p->background = 0;
4542c20d
HJYP
234 panel_update_background( p );
235 //restart();
368409ba 236 }
a52c2257
HJYP
237 RET();
238}
239
2de71c90 240static void
8110399f 241background_toggle( GtkWidget *b, Panel* p)
2de71c90 242{
4b93d81e
HJYP
243 GtkWidget* fc = ptk_ui_xml_get_widget( gtk_widget_get_toplevel(b), "img_file" );
244 gtk_widget_set_sensitive( fc, gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b)));
368409ba 245 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b))) {
6576fd40
FC
246 if (!p->background) {
247 p->transparent = 0;
248 p->background = 1;
be933927 249 /* Update background immediately. */
4542c20d
HJYP
250 panel_update_background( p );
251 //restart();
252 }
14f92387 253 }
2de71c90
FC
254}
255
256static void
8110399f 257background_changed(GtkFileChooser *file_chooser, Panel* p )
2de71c90 258{
781afa7b 259 p->transparent = 0;
1970b674 260 p->background = 1;
2de71c90 261 p->background_file = g_strdup(gtk_file_chooser_get_filename(file_chooser));
be933927 262 /* Update background immediately. */
4542c20d
HJYP
263 panel_update_background( p );
264 //restart();
2de71c90
FC
265}
266
781afa7b 267static void
8110399f 268background_disable_toggle( GtkWidget *b, Panel* p )
781afa7b
FC
269{
270 ENTER;
271 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b))) {
6576fd40
FC
272 if (p->background!=0||p->transparent!=0) {
273 p->background = 0;
274 p->transparent = 0;
be933927 275 /* Update background immediately. */
4542c20d
HJYP
276 panel_update_background( p );
277 //restart();
6576fd40 278 }
781afa7b
FC
279 }
280
781afa7b
FC
281 RET();
282}
283
d2669858 284static void
8110399f 285on_font_color_set( GtkColorButton* clr, Panel* p )
d2669858 286{
cf701cb7
HJYP
287 gtk_color_button_get_color( clr, &p->gfontcolor );
288 /* FIXME: need some better mechanism to update the panel */
289 if( p->usefontcolor )
290 gtk_widget_queue_draw( p->topgwin );
d2669858
HJYP
291}
292
cf701cb7 293static void
8110399f 294on_use_font_color_toggled( GtkToggleButton* btn, Panel* p )
d2669858 295{
cf701cb7
HJYP
296 GtkWidget* clr = (GtkWidget*)g_object_get_data( btn, "clr" );
297 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(btn)))
298 gtk_widget_set_sensitive( clr, TRUE );
299 else
300 gtk_widget_set_sensitive( clr, FALSE );
301 p->usefontcolor = gtk_toggle_button_get_active( btn );
302 /* FIXME: need some better mechanism to update the panel */
303 gtk_widget_queue_draw( p->topgwin );
d2669858
HJYP
304}
305
bee4c26e 306static void
8110399f 307set_dock_type(GtkToggleButton* toggle, Panel* p )
bee4c26e
HJYP
308{
309 p->setdocktype = gtk_toggle_button_get_active(toggle) ? 1 : 0;
310 panel_set_dock_type( p );
8110399f 311 update_panel_geometry(p);
bee4c26e
HJYP
312 /* FIXME: apparently, this doesn't work,
313 but we don't know the reason yet! */
314}
315
316static void
8110399f 317set_struct(GtkToggleButton* toggle, Panel* p )
bee4c26e
HJYP
318{
319 p->setstrut = gtk_toggle_button_get_active(toggle) ? 1 : 0;
8110399f 320 update_panel_geometry(p);
bee4c26e
HJYP
321}
322
ce522551 323static void
04883e73 324on_sel_plugin_changed( GtkTreeSelection* tree_sel, GtkWidget* label )
a52c2257 325{
8ccd023a
HJYP
326 GtkTreeIter it;
327 GtkTreeModel* model;
22242ed4 328 Plugin* pl;
a52c2257 329
8ccd023a
HJYP
330 if( gtk_tree_selection_get_selected( tree_sel, &model, &it ) )
331 {
cfc83537 332 GtkTreeView* view = gtk_tree_selection_get_tree_view( tree_sel );
5a343ad5 333 GtkWidget *edit_btn = GTK_WIDGET(g_object_get_data( G_OBJECT(view), "edit_btn" ));
8ccd023a 334 gtk_tree_model_get( model, &it, 1, &pl, -1 );
5a343ad5 335 gtk_label_set_text( GTK_LABEL(label), _(pl->class->description) );
cfc83537 336 gtk_widget_set_sensitive( edit_btn, pl->class->config != NULL );
8ccd023a 337 }
ce522551 338}
a52c2257 339
8110399f 340static void init_plugin_list( Panel* p, GtkTreeView* view, GtkWidget* label )
ce522551 341{
ce522551
HJYP
342 GtkListStore* list;
343 GtkTreeViewColumn* col;
344 GtkCellRenderer* render;
345 GtkTreeSelection* tree_sel;
346 GList* l;
8ccd023a 347 GtkTreeIter it;
ce522551 348
cf701cb7 349 g_object_set_data( view, "panel", p );
8110399f 350
ce522551
HJYP
351 render = gtk_cell_renderer_text_new();
352 col = gtk_tree_view_column_new_with_attributes(
353 _("Currently loaded plugins"),
354 render, "text", 0, NULL );
355 gtk_tree_view_append_column( view, col );
356
357 list = gtk_list_store_new( 2, G_TYPE_STRING, G_TYPE_POINTER );
358 for( l = p->plugins; l; l = l->next )
359 {
360 GtkTreeIter it;
22242ed4 361 Plugin* pl = (Plugin*)l->data;
ce522551
HJYP
362 gtk_list_store_append( list, &it );
363 gtk_list_store_set( list, &it,
364 0, _(pl->class->name),
365 1, pl, -1);
366 }
367 gtk_tree_view_set_model( view, GTK_TREE_MODEL( list ) );
389975e0
HJYP
368 g_signal_connect( view, "row-activated",
369 G_CALLBACK(modify_plugin), NULL );
ce522551 370 tree_sel = gtk_tree_view_get_selection( view );
16fb8c2e 371 gtk_tree_selection_set_mode( tree_sel, GTK_SELECTION_BROWSE );
ce522551 372 g_signal_connect( tree_sel, "changed",
04883e73 373 G_CALLBACK(on_sel_plugin_changed), label);
8ccd023a
HJYP
374 if( gtk_tree_model_get_iter_first( GTK_TREE_MODEL(list), &it ) )
375 gtk_tree_selection_select_iter( tree_sel, &it );
ce522551
HJYP
376}
377
16fb8c2e
HJYP
378static void on_add_plugin_response( GtkDialog* dlg,
379 int response,
380 GtkTreeView* _view )
ce522551 381{
cf701cb7 382 Panel* p = (Panel*) g_object_get_data( _view, "panel" );
16fb8c2e
HJYP
383 if( response == GTK_RESPONSE_OK )
384 {
385 GtkTreeView* view;
386 GtkTreeSelection* tree_sel;
387 GtkTreeIter it;
388 GtkTreeModel* model;
389
67e88af2 390 view = (GtkTreeView*)g_object_get_data( G_OBJECT(dlg), "avail-plugins" );
16fb8c2e
HJYP
391 tree_sel = gtk_tree_view_get_selection( view );
392 if( gtk_tree_selection_get_selected( tree_sel, &model, &it ) )
393 {
394 char* type = NULL;
22242ed4 395 Plugin* pl;
16fb8c2e
HJYP
396 gtk_tree_model_get( model, &it, 1, &type, -1 );
397 if( pl = plugin_load( type ) )
398 {
1d0f0857
HJYP
399 GtkTreePath* tree_path;
400
16fb8c2e
HJYP
401 pl->panel = p;
402 plugin_start( pl, NULL );
1d0f0857 403 p->plugins = g_list_append(p->plugins, pl);
5297da29
HJYP
404 /* FIXME: will show all cause problems? */
405 gtk_widget_show_all( pl->pwid );
1d0f0857 406
cf701cb7 407 /* update background of the newly added plugin */
f37da9d7
HJYP
408 plugin_widget_set_background( pl->pwid, pl->panel );
409
1d0f0857
HJYP
410 model = gtk_tree_view_get_model( _view );
411 gtk_list_store_append( (GtkListStore*)model, &it );
412 gtk_list_store_set( (GtkListStore*)model, &it,
413 0, _(pl->class->name),
414 1, pl, -1 );
415 tree_sel = gtk_tree_view_get_selection( _view );
416 gtk_tree_selection_select_iter( tree_sel, &it );
417 if( tree_path = gtk_tree_model_get_path( model, &it ) )
418 {
419 gtk_tree_view_scroll_to_cell( _view, tree_path, NULL, FALSE, 0, 0 );
420 gtk_tree_path_free( tree_path );
421 }
16fb8c2e
HJYP
422 }
423 g_free( type );
424 }
425 }
1d0f0857
HJYP
426/*
427 gtk_widget_set_sensitive( (GtkWidget*)gtk_window_get_transient_for( (GtkWindow*)dlg ),
428 TRUE );
429*/
16fb8c2e
HJYP
430 gtk_widget_destroy( (GtkWidget*)dlg );
431}
432
433static void on_add_plugin( GtkButton* btn, GtkTreeView* _view )
434{
435 GtkWidget* dlg, *parent_win, *scroll;
436 GList* classes;
6a6ad54e 437 GList* tmp;
16fb8c2e
HJYP
438 GtkTreeViewColumn* col;
439 GtkCellRenderer* render;
440 GtkTreeView* view;
441 GtkListStore* list;
442 GtkTreeSelection* tree_sel;
443
cf701cb7 444 Panel* p = (Panel*) g_object_get_data( _view, "panel" );
8110399f 445
16fb8c2e
HJYP
446 classes = plugin_get_available_classes();
447
448 parent_win = gtk_widget_get_toplevel( (GtkWidget*)_view );
449 dlg = gtk_dialog_new_with_buttons( _("Add plugin to panel"),
67e88af2 450 GTK_WINDOW(parent_win), 0,
16fb8c2e
HJYP
451 GTK_STOCK_CANCEL,
452 GTK_RESPONSE_CANCEL,
453 GTK_STOCK_ADD,
454 GTK_RESPONSE_OK, NULL );
5420dd00
FC
455
456 /* fix background */
5b6ce65c
FC
457 if (p->background)
458 gtk_widget_set_style(dlg, p->defstyle);
5420dd00 459
1d0f0857 460 /* gtk_widget_set_sensitive( parent_win, FALSE ); */
16fb8c2e
HJYP
461 scroll = gtk_scrolled_window_new( NULL, NULL );
462 gtk_scrolled_window_set_shadow_type( (GtkScrolledWindow*)scroll,
463 GTK_SHADOW_IN );
464 gtk_scrolled_window_set_policy((GtkScrolledWindow*)scroll,
465 GTK_POLICY_AUTOMATIC,
466 GTK_POLICY_AUTOMATIC );
467 gtk_box_pack_start( (GtkBox*)GTK_DIALOG(dlg)->vbox, scroll,
468 TRUE, TRUE, 4 );
67e88af2 469 view = (GtkTreeView*)gtk_tree_view_new();
16fb8c2e
HJYP
470 gtk_container_add( (GtkContainer*)scroll, view );
471 tree_sel = gtk_tree_view_get_selection( view );
472 gtk_tree_selection_set_mode( tree_sel, GTK_SELECTION_BROWSE );
473
474 render = gtk_cell_renderer_text_new();
475 col = gtk_tree_view_column_new_with_attributes(
476 _("Available plugins"),
477 render, "text", 0, NULL );
478 gtk_tree_view_append_column( view, col );
479
480 list = gtk_list_store_new( 2,
481 G_TYPE_STRING,
482 G_TYPE_STRING );
483
6a6ad54e 484 for( tmp = classes; tmp; tmp = tmp->next ) {
22242ed4 485 PluginClass* pc = (PluginClass*)tmp->data;
16fb8c2e
HJYP
486 if( ! pc->invisible ) {
487 /* FIXME: should we display invisible plugins? */
488 GtkTreeIter it;
489 gtk_list_store_append( list, &it );
490 gtk_list_store_set( list, &it,
491 0, _(pc->name),
492 1, pc->type, -1 );
493 /* g_debug( "%s (%s)", pc->type, _(pc->name) ); */
494 }
6a6ad54e 495 }
16fb8c2e
HJYP
496
497 gtk_tree_view_set_model( view, GTK_TREE_MODEL(list) );
498 g_object_unref( list );
499
500 g_signal_connect( dlg, "response",
501 on_add_plugin_response, _view );
502 g_object_set_data( dlg, "avail-plugins", view );
503 g_object_weak_ref( dlg, plugin_class_list_free, classes );
504
1d0f0857 505 gtk_window_set_default_size( (GtkWindow*)dlg, 320, 400 );
16fb8c2e 506 gtk_widget_show_all( dlg );
ce522551
HJYP
507}
508
04883e73 509static void on_remove_plugin( GtkButton* btn, GtkTreeView* view )
ce522551 510{
8ccd023a
HJYP
511 GtkTreeIter it;
512 GtkTreePath* tree_path;
513 GtkTreeModel* model;
514 GtkTreeSelection* tree_sel = gtk_tree_view_get_selection( view );
22242ed4 515 Plugin* pl;
ce522551 516
cf701cb7 517 Panel* p = (Panel*) g_object_get_data( view, "panel" );
8110399f 518
8ccd023a
HJYP
519 if( gtk_tree_selection_get_selected( tree_sel, &model, &it ) )
520 {
521 tree_path = gtk_tree_model_get_path( model, &it );
522 gtk_tree_model_get( model, &it, 1, &pl, -1 );
523 if( gtk_tree_path_get_indices(tree_path)[0] >= gtk_tree_model_iter_n_children( model, NULL ) )
524 gtk_tree_path_prev( tree_path );
525 gtk_list_store_remove( GTK_LIST_STORE(model), &it );
526 p->plugins = g_list_remove( p->plugins, pl );
527 plugin_stop( pl ); /* free the plugin widget & its data */
4542c20d 528 plugin_put( pl ); /* free the lib if necessary */
8ccd023a
HJYP
529
530 gtk_tree_selection_select_path( tree_sel, tree_path );
531 gtk_tree_path_free( tree_path );
532 }
ce522551
HJYP
533}
534
389975e0 535void modify_plugin( GtkTreeView* view )
04883e73
HJYP
536{
537 GtkTreeSelection* tree_sel = gtk_tree_view_get_selection( view );
538 GtkTreeModel* model;
539 GtkTreeIter it;
22242ed4 540 Plugin* pl;
04883e73
HJYP
541
542 if( ! gtk_tree_selection_get_selected( tree_sel, &model, &it ) )
543 return;
544
545 gtk_tree_model_get( model, &it, 1, &pl, -1 );
546 if( pl->class->config )
5a343ad5 547 pl->class->config( pl, (GtkWindow*)gtk_widget_get_toplevel(GTK_WIDGET(view)) );
04883e73
HJYP
548}
549
cf701cb7 550static int get_widget_index( Panel* p, Plugin* pl )
ce522551
HJYP
551{
552 GList* l;
553 int i;
554 for( i = 0, l = p->plugins; l; l = l->next )
555 {
22242ed4 556 Plugin* _pl = (Plugin*)l->data;
ce522551
HJYP
557 if( _pl == pl )
558 return i;
559 if( _pl->pwid )
560 ++i;
561 }
562 return -1;
563}
564
565static void on_moveup_plugin( GtkButton* btn, GtkTreeView* view )
566{
567 GList *l;
568 GtkTreeIter it, prev;
569 GtkTreeModel* model = gtk_tree_view_get_model( view );
570 GtkTreeSelection* tree_sel = gtk_tree_view_get_selection( view );
571 int i;
572
cf701cb7 573 Panel* panel = (Panel*) g_object_get_data( view, "panel" );
8110399f 574
ce522551
HJYP
575 if( ! gtk_tree_model_get_iter_first( model, &it ) )
576 return;
577 if( gtk_tree_selection_iter_is_selected( tree_sel, &it ) )
578 return;
579 do{
580 if( gtk_tree_selection_iter_is_selected(tree_sel, &it) )
581 {
22242ed4 582 Plugin* pl;
ce522551
HJYP
583 gtk_tree_model_get( model, &it, 1, &pl, -1 );
584 gtk_list_store_move_before( GTK_LIST_STORE( model ),
585 &it, &prev );
586
587 i = 0;
8110399f 588 for( l = panel->plugins; l; l = l->next, ++i )
ce522551
HJYP
589 {
590 if( l->data == pl )
591 {
8110399f
HJYP
592 panel->plugins = g_list_insert( panel->plugins, pl, i - 1);
593 panel->plugins = g_list_delete_link( panel->plugins, l);
ce522551
HJYP
594 }
595 }
596 if( pl->pwid )
597 {
8110399f 598 gtk_box_reorder_child( GTK_BOX(panel->box), pl->pwid, get_widget_index( panel, pl ) );
ce522551
HJYP
599 }
600 return;
601 }
602 prev = it;
603 }while( gtk_tree_model_iter_next( model, &it ) );
604}
605
606static void on_movedown_plugin( GtkButton* btn, GtkTreeView* view )
607{
608 GList *l;
609 GtkTreeIter it, next;
610 GtkTreeModel* model;
611 GtkTreeSelection* tree_sel = gtk_tree_view_get_selection( view );
22242ed4 612 Plugin* pl;
ce522551
HJYP
613 int i;
614
cf701cb7 615 Panel* panel = (Panel*) g_object_get_data( view, "panel" );
8110399f 616
ce522551
HJYP
617 if( ! gtk_tree_selection_get_selected( tree_sel, &model, &it ) )
618 return;
619 next = it;
620
621 if( ! gtk_tree_model_iter_next( model, &next) )
622 return;
623
624 gtk_tree_model_get( model, &it, 1, &pl, -1 );
625
626 gtk_list_store_move_after( GTK_LIST_STORE( model ), &it, &next );
627
628 i = 0;
8110399f 629 for( l = panel->plugins; l; l = l->next, ++i )
ce522551
HJYP
630 {
631 if( l->data == pl )
632 {
8110399f
HJYP
633 panel->plugins = g_list_insert( panel->plugins, pl, i + 2);
634 panel->plugins = g_list_delete_link( panel->plugins, l);
ce522551
HJYP
635 }
636 }
637 if( pl->pwid )
638 {
8110399f 639 gtk_box_reorder_child( GTK_BOX(panel->box), pl->pwid, get_widget_index( panel, pl ) );
ce522551
HJYP
640 }
641}
642
a52c2257
HJYP
643static void
644update_opt_menu(GtkWidget *w, int ind)
645{
646 int i;
647
648 ENTER;
649 /* this trick will trigger "changed" signal even if active entry is
650 * not actually changing */
651 i = gtk_combo_box_get_active(GTK_COMBO_BOX(w));
652 if (i == ind) {
653 i = i ? 0 : 1;
654 gtk_combo_box_set_active(GTK_COMBO_BOX(w), i);
655 }
656 gtk_combo_box_set_active(GTK_COMBO_BOX(w), ind);
657 RET();
658}
659
660static void
661update_toggle_button(GtkWidget *w, gboolean n)
662{
663 gboolean c;
664
665 ENTER;
666 /* this trick will trigger "changed" signal even if active entry is
667 * not actually changing */
668 c = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w));
669 if (c == n) {
670 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), !n);
671 }
672 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), n);
673 RET();
674}
675
a52c2257 676void
4b93d81e 677panel_configure( Panel* p, int sel_page )
a52c2257 678{
4b93d81e
HJYP
679 PtkUIXml* xml;
680 GtkWidget *w, *w2;
681
682 if( p->pref_dialog )
683 {
684 gtk_window_present((GtkWindow*)p->pref_dialog);
685 return;
686 }
687
688 p->pref_dialog = ptk_ui_xml_create_widget_from_file( PACKAGE_DATA_DIR "/lxpanel/ui/panel-pref.glade" );
689 g_signal_connect(p->pref_dialog, "response", (GCallback) response_event, p);
690 g_object_add_weak_pointer( p->pref_dialog, &p->pref_dialog );
691 gtk_window_set_position( (GtkWindow*)p->pref_dialog, GTK_WIN_POS_CENTER );
692
693 xml = ptk_ui_xml_get( p->pref_dialog );
694 /* position */
695 w = ptk_ui_xml_lookup( xml, "edge" );
696 update_opt_menu( w, p->edge - 1 );
697 g_signal_connect( w, "changed", G_CALLBACK(set_edge), p);
698
699 w = ptk_ui_xml_lookup( xml, "align" );
700 update_opt_menu( w, p->allign - 1 );
701 g_signal_connect( w, "changed", G_CALLBACK(set_allign), p);
702
703 w = ptk_ui_xml_lookup( xml, "margin" );
704 gtk_spin_button_set_value( (GtkSpinButton*)w, p->margin );
705 g_signal_connect( w, "value-changed",
706 G_CALLBACK(set_margin), p);
707
708 /* size */
709 w = ptk_ui_xml_lookup( xml, "width" );
710 gtk_widget_set_sensitive( w, p->widthtype != WIDTH_REQUEST );
711 if( p->widthtype == WIDTH_PERCENT) {
712 gtk_spin_button_set_range( (GtkSpinButton*)w, 0, 100 );
713 } else if( p->widthtype == WIDTH_PIXEL) {
714 gtk_spin_button_set_range( (GtkSpinButton*)w, 0, gdk_screen_width() );
715 }
716 gtk_spin_button_set_value( (GtkSpinButton*)w, p->width );
717 g_signal_connect( w, "value-changed", G_CALLBACK(set_width), p );
718
719 w = ptk_ui_xml_lookup( xml, "width_unit" );
720 update_opt_menu( w, p->widthtype - 1 );
721 g_signal_connect( w, "changed",
722 G_CALLBACK(set_width_type), p);
723
724 w = ptk_ui_xml_lookup( xml, "height" );
725 gtk_spin_button_set_value( (GtkSpinButton*)w, p->height );
726 g_signal_connect( w, "value-changed", G_CALLBACK(set_height), p );
727
728 w = ptk_ui_xml_lookup( xml, "height_unit" );
729 update_opt_menu( w, HEIGHT_PIXEL - 1);
730 //g_signal_connect( w, "changed", G_CALLBACK(set_height_type), NULL);
731
732 /* properties */
733
734 /* Explaination from Ruediger Arp <ruediger@gmx.net>:
735 "Set Dock Type", it is referring to the behaviour of
736 dockable applications such as those found in WindowMaker (e.g.
737 http://www.cs.mun.ca/~gstarkes/wmaker/dockapps ) and other
738 lightweight window managers. These dockapps are probably being
739 treated in some special way.
740 */
741 w = ptk_ui_xml_lookup( xml, "as_dock" );
742 update_toggle_button( w, p->setdocktype );
743 g_signal_connect( w, "toggled",
744 G_CALLBACK(set_dock_type), p );
745
746 /* Explaination from Ruediger Arp <ruediger@gmx.net>:
747 "Set Strut": Reserve panel's space so that it will not be
748 covered by maximazied windows.
749 This is clearly an option to avoid the panel being
750 covered/hidden by other applications so that it always is
751 accessible. The panel "steals" some screen estate which cannot
752 be accessed by other applications.
753 GNOME Panel acts this way, too.
754 */
755 w = ptk_ui_xml_lookup( xml, "reserve_space" );
756 update_toggle_button( w, p->setstrut );
757 g_signal_connect( w, "toggled",
758 G_CALLBACK(set_struct), p );
759
760 /* transparancy */
761 w = ptk_ui_xml_lookup( xml, "tint_clr" );
762 gtk_color_button_set_color((GtkColorButton*)w, &p->gtintcolor);
763 gtk_color_button_set_alpha((GtkColorButton*)w, 256*p->alpha);
764 if ( ! p->transparent )
765 gtk_widget_set_sensitive( w, FALSE );
766
767 /* background */
768 {
769 GtkWidget* none, *trans, *img;
770 GSList* group;
771 none = ptk_ui_xml_lookup( xml, "bg_none" );
772 trans = ptk_ui_xml_lookup( xml, "bg_transparency" );
773 img = ptk_ui_xml_lookup( xml, "bg_image" );
774
775 group = gtk_radio_button_get_group( (GtkRadioButton*)none );
776 gtk_radio_button_set_group( (GtkRadioButton*)trans, group );
777 group = gtk_radio_button_get_group( (GtkRadioButton*)trans );
778 gtk_radio_button_set_group( (GtkRadioButton*)img, group );
779
780 if (p->background)
781 gtk_toggle_button_set_active( (GtkToggleButton*)img, TRUE);
782 else if (p->transparent)
783 gtk_toggle_button_set_active( (GtkToggleButton*)trans, TRUE);
784 else
785 gtk_toggle_button_set_active( (GtkToggleButton*)none, TRUE);
786
787 g_signal_connect(none, "toggled", G_CALLBACK(background_disable_toggle), p);
788 g_signal_connect(trans, "toggled", G_CALLBACK(transparency_toggle), p);
789 g_signal_connect(img, "toggled", G_CALLBACK(background_toggle), p);
790
791 w = ptk_ui_xml_lookup( xml, "img_file" );
792 gtk_file_chooser_set_current_folder( (GtkFileChooser*)w, PACKAGE_DATA_DIR "/lxpanel/images");
793 if (p->background_file)
794 gtk_file_chooser_set_filename( (GtkFileChooser*)w, p->background_file);
795
796 if (!p->background)
797 gtk_widget_set_sensitive( w, FALSE);
798
799 /* FIXME: Important!! */
800 /* This is only available in gtk+ >= 2.12 */
801 /* Use gtk_file_chooser_button_new_with_dialog and intercept "response" signal instead. */
802 g_signal_connect( w, "file-set", G_CALLBACK (background_changed), p);
803 }
804
805 /* font color */
806 w = ptk_ui_xml_lookup( xml, "font_clr" );
807 gtk_color_button_set_color( (GtkColorButton*)w, &p->gfontcolor );
808 g_signal_connect( w, "color-set", G_CALLBACK( on_font_color_set ), p );
809
810 w2 = ptk_ui_xml_lookup( xml, "use_font_clr" );
811 gtk_toggle_button_set_active( (GtkToggleButton*)w2, p->usefontcolor );
812 g_object_set_data( w2, "clr", w );
813 g_signal_connect(w2, "toggled", G_CALLBACK(on_use_font_color_toggled), p);
814 if( ! p->usefontcolor )
815 gtk_widget_set_sensitive( w, FALSE );
816
817 /* plugin list */
818 {
819 GtkWidget* plugin_list = ptk_ui_xml_lookup( xml, "plugin_list" );
820
821 /* buttons used to edit plugin list */
822 w = ptk_ui_xml_lookup( xml, "add_btn" );
823 g_signal_connect( w, "clicked", G_CALLBACK(on_add_plugin), plugin_list );
824
825 w = ptk_ui_xml_lookup( xml, "edit_btn" );
826 g_signal_connect_swapped( w, "clicked", G_CALLBACK(modify_plugin), plugin_list );
827 g_object_set_data( G_OBJECT(plugin_list), "edit_btn", w );
828
829 w = ptk_ui_xml_lookup( xml, "remove_btn" );
830 g_signal_connect( w, "clicked", G_CALLBACK(on_remove_plugin), plugin_list );
831 w = ptk_ui_xml_lookup( xml, "moveup_btn" );
832 g_signal_connect( w, "clicked", G_CALLBACK(on_moveup_plugin), plugin_list );
833 w = ptk_ui_xml_lookup( xml, "movedown_btn" );
834 g_signal_connect( w, "clicked", G_CALLBACK(on_movedown_plugin), plugin_list );
835
836 w = ptk_ui_xml_lookup( xml, "plugin_desc" );
837 init_plugin_list( p, (GtkTreeView*)plugin_list, w );
838 }
839 /* advanced, applications */
840 w = ptk_ui_xml_lookup( xml, "file_manager" );
841 if (file_manager_cmd)
842 gtk_entry_set_text( (GtkEntry*)w, file_manager_cmd );
843 g_signal_connect( w, "changed",
844 G_CALLBACK(on_entry_changed),
845 &file_manager_cmd);
846
847 w = ptk_ui_xml_lookup( xml, "term" );
848 if (terminal_cmd)
849 gtk_entry_set_text( (GtkEntry*)w, terminal_cmd );
850 g_signal_connect( w, "changed",
851 G_CALLBACK(on_entry_changed),
852 &terminal_cmd);
853
854 /* If we are under LXSession, setting logout command is not necessary. */
855 w = ptk_ui_xml_lookup( xml, "logout" );
856 if( getenv("_LXSESSION_PID") ) {
857 gtk_widget_hide( w );
858 w = ptk_ui_xml_lookup( xml, "logout_label" );
859 gtk_widget_hide( w );
860 }
861 else {
862 if(logout_cmd)
863 gtk_entry_set_text( (GtkEntry*)w, logout_cmd );
864 g_signal_connect( w, "changed",
865 G_CALLBACK(on_entry_changed),
866 &logout_cmd);
867 }
868
869 gtk_widget_show((GtkWindow*)p->pref_dialog);
870 w = ptk_ui_xml_get_widget( p->pref_dialog, "notebook" );
871 gtk_notebook_set_current_page( (GtkNotebook*)w, sel_page );
a52c2257
HJYP
872}
873
874void
cf701cb7 875panel_global_config_save( Panel* p, FILE *fp)
a52c2257
HJYP
876{
877 GdkColor c;
04883e73 878
4b93d81e
HJYP
879 fprintf(fp, "# lxpanel <profile> config file. Manually editing is not recommended.\n"
880 "# Use preference dialog in lxpanel to adjust config when you can.\n\n");
389975e0 881 lxpanel_put_line(fp, "Global {");
4b93d81e
HJYP
882 lxpanel_put_str(fp, "edge", num2str(edge_pair, p->edge, "none"));
883 lxpanel_put_str(fp, "allign", num2str(allign_pair, p->allign, "none"));
884 lxpanel_put_int(fp, "margin", p->margin);
885 lxpanel_put_str(fp, "widthtype", num2str(width_pair, p->widthtype, "none"));
886 lxpanel_put_int(fp, "width", p->width);
887 lxpanel_put_int(fp, "height", p->height);
888 lxpanel_put_bool(fp, "transparent", p->transparent );
889// gtk_color_button_get_color(GTK_COLOR_BUTTON(tr_colorb), &c);
890 lxpanel_put_line(fp, "tintcolor=#%06x", gcolor2rgb24(&p->gtintcolor));
891// lxpanel_put_int(fp, "alpha", gtk_color_button_get_alpha(GTK_COLOR_BUTTON(tr_colorb)) * 0xff / 0xffff);
892/* FIXME: is this correct?? */
893 lxpanel_put_int(fp, "alpha", p->alpha * 0xff / 0xffff);
894 lxpanel_put_bool(fp, "setdocktype", p->setdocktype);
895 lxpanel_put_bool(fp, "setpartialstrut", p->setstrut);
896 lxpanel_put_bool(fp, "usefontcolor", p->usefontcolor);
897 lxpanel_put_line(fp, "fontcolor=#%06x", gcolor2rgb24(&p->gfontcolor));
898 lxpanel_put_bool(fp, "background", p->background );
899 lxpanel_put_str(fp, "backgroundfile", p->background_file );
389975e0 900 lxpanel_put_line(fp, "}\n");
a52c2257
HJYP
901}
902
a52c2257 903void
cf701cb7 904panel_plugin_config_save( Panel* p, FILE *fp)
a52c2257 905{
9c97f69e
HJYP
906 GList* l;
907 for( l = p->plugins; l; l = l->next )
908 {
22242ed4 909 Plugin* pl = (Plugin*)l->data;
9c97f69e
HJYP
910 lxpanel_put_line( fp, "Plugin {" );
911 lxpanel_put_line( fp, "type = %s", pl->class->type );
da76d5cf
HJYP
912 if( pl->expand )
913 lxpanel_put_bool( fp, "expand", TRUE );
914 if( pl->padding > 0 )
915 lxpanel_put_int( fp, "padding", pl->padding );
916 if( pl->border > 0 )
917 lxpanel_put_int( fp, "border", pl->border );
918
9c97f69e
HJYP
919 if( pl->class->save )
920 {
921 lxpanel_put_line( fp, "Config {" );
922 pl->class->save( pl, fp );
923 lxpanel_put_line( fp, "}" );
a52c2257 924 }
9c97f69e 925 lxpanel_put_line( fp, "}\n" );
a52c2257 926 }
a52c2257
HJYP
927}
928
cf701cb7 929void panel_config_save( Panel* p )
368409ba 930{
8110399f 931 gchar *fname, *dir;
368409ba 932 FILE *fp;
24053345 933
cf701cb7 934 dir = get_config_file( cprofile, "panels", FALSE );
8110399f 935 fname = g_build_filename( dir, p->name, NULL );
4b93d81e
HJYP
936
937 /* ensure the 'panels' dir exists */
938 if( ! g_file_test( dir, G_FILE_TEST_EXISTS ) )
939 g_mkdir_with_parents( dir, 0755 );
8110399f 940 g_free( dir );
24053345 941
368409ba
FC
942 if (!(fp = fopen(fname, "w"))) {
943 ERR("can't open for write %s:", fname);
4b93d81e 944 g_free( fname );
368409ba
FC
945 perror(NULL);
946 RET();
947 }
cf701cb7
HJYP
948 panel_global_config_save(p, fp);
949 panel_plugin_config_save(p, fp);
368409ba 950 fclose(fp);
24053345 951 g_free( fname );
cf701cb7
HJYP
952
953 /* save the global config file */
954 save_global_config();
368409ba
FC
955}
956
389975e0 957void restart(void)
a52c2257 958{
f7cb330e
HJYP
959 /* This is defined in panel.c */
960 extern gboolean is_restarting;
a52c2257 961 ENTER;
f7cb330e 962 is_restarting = TRUE;
be933927
HJYP
963
964 /* processing any possible idle handlers before we restart */
965 while (gtk_events_pending ())
966 gtk_main_iteration ();
f7cb330e 967 gtk_main_quit();
a52c2257
HJYP
968 RET();
969}
970
389975e0
HJYP
971void logout(void)
972{
cf701cb7 973 const char* logout_cmd = logout_cmd;
00555dcf 974 /* If LXSession is running, _LXSESSION_PID will be set */
cf701cb7
HJYP
975 if( ! logout_cmd && getenv("_LXSESSION_PID") )
976 logout_cmd = "lxsession-logout";
00555dcf 977
cf701cb7 978 if( logout_cmd ) {
389975e0 979 GError* err = NULL;
cf701cb7 980 if( ! g_spawn_command_line_async( logout_cmd, &err ) ) {
389975e0
HJYP
981 show_error( NULL, err->message );
982 g_error_free( err );
983 }
984 }
985 else {
986 show_error( NULL, _("Logout command is not set") );
987 }
988}
989
04883e73
HJYP
990static void notify_apply_config( GtkWidget* widget )
991{
992 GSourceFunc apply_func;
993 GtkWidget* dlg;
994
995 dlg = gtk_widget_get_toplevel( widget );
5a343ad5 996 apply_func = g_object_get_data( G_OBJECT(dlg), "apply_func" );
04883e73 997 if( apply_func )
5a343ad5 998 apply_func( g_object_get_data(G_OBJECT(dlg), "plugin") );
04883e73
HJYP
999}
1000
1001static void on_entry_changed( GtkEditable* edit, gpointer user_data )
1002{
1003 char** val = (char**)user_data;
f7cb330e 1004 const char *new_val;
04883e73 1005 g_free( *val );
f7cb330e
HJYP
1006 new_val = gtk_entry_get_text(GTK_ENTRY(edit));
1007 *val = (new_val && *new_val) ? g_strdup( new_val ) : NULL;
5a343ad5 1008 notify_apply_config( GTK_WIDGET(edit) );
04883e73
HJYP
1009}
1010
1011static void on_spin_changed( GtkSpinButton* spin, gpointer user_data )
1012{
1013 int* val = (int*)user_data;
1014 *val = (int)gtk_spin_button_get_value( spin );
5a343ad5 1015 notify_apply_config( GTK_WIDGET(spin) );
04883e73
HJYP
1016}
1017
1018static void on_toggle_changed( GtkToggleButton* btn, gpointer user_data )
1019{
1020 gboolean* val = (gboolean*)user_data;
1021 *val = gtk_toggle_button_get_active( btn );
5a343ad5 1022 notify_apply_config( GTK_WIDGET(btn) );
04883e73
HJYP
1023}
1024
bb6d6422 1025/* Parameters: const char* name, gpointer ret_value, GType type, ....NULL */
04883e73
HJYP
1026GtkWidget* create_generic_config_dlg( const char* title, GtkWidget* parent,
1027 GSourceFunc apply_func, gpointer plugin,
1028 const char* name, ... )
bb6d6422
HJYP
1029{
1030 va_list args;
cf701cb7 1031 Panel* p = ((Plugin*)plugin)->panel;
5a343ad5 1032 GtkWidget* dlg = gtk_dialog_new_with_buttons( title, GTK_WINDOW(parent), 0,
04883e73
HJYP
1033 GTK_STOCK_CLOSE,
1034 GTK_RESPONSE_CLOSE,
1035 NULL );
1036
5420dd00 1037 /* fix background */
5b6ce65c
FC
1038 if (p->background)
1039 gtk_widget_set_style(dlg, p->defstyle);
5420dd00 1040
04883e73
HJYP
1041 /* this is a dirty hack. We need to check if this response is GTK_RESPONSE_CLOSE or not. */
1042 g_signal_connect( dlg, "response", G_CALLBACK(gtk_widget_destroy), NULL );
1043 if( apply_func )
5a343ad5 1044 g_object_set_data( G_OBJECT(dlg), "apply_func", apply_func );
04883e73 1045 if( plugin )
5a343ad5 1046 g_object_set_data( G_OBJECT(dlg), "plugin", plugin );
04883e73 1047
5a343ad5 1048 gtk_box_set_spacing( GTK_BOX(GTK_DIALOG(dlg)->vbox), 4 );
04883e73 1049
bb6d6422
HJYP
1050 va_start( args, name );
1051 while( name )
1052 {
1053 GtkWidget* label = gtk_label_new( name );
1054 GtkWidget* entry = NULL;
1055 gpointer val = va_arg( args, gpointer );
1056 GType type = va_arg( args, GType );
1057 switch( type )
1058 {
1059 case G_TYPE_STRING:
1060 entry = gtk_entry_new();
7414a73f
HJYP
1061 if( *(char**)val )
1062 gtk_entry_set_text( GTK_ENTRY(entry), *(char**)val );
16fb8c2e 1063 g_signal_connect( entry, "changed",
92d76f06 1064 G_CALLBACK(on_entry_changed), val );
bb6d6422
HJYP
1065 break;
1066 case G_TYPE_INT:
1067 {
1068 /* FIXME: the range shouldn't be hardcoded */
1069 entry = gtk_spin_button_new_with_range( 0, 1000, 1 );
5a343ad5 1070 gtk_spin_button_set_value( GTK_SPIN_BUTTON(entry), *(int*)val );
16fb8c2e 1071 g_signal_connect( entry, "value-changed",
92d76f06 1072 G_CALLBACK(on_spin_changed), val );
bb6d6422
HJYP
1073 break;
1074 }
1075 case G_TYPE_BOOLEAN:
1076 entry = gtk_check_button_new();
5a343ad5
JH
1077 gtk_container_add( GTK_CONTAINER(entry), label );
1078 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(entry), *(gboolean*)val );
16fb8c2e 1079 g_signal_connect( entry, "toggled",
92d76f06 1080 G_CALLBACK(on_toggle_changed), val );
bb6d6422
HJYP
1081 break;
1082 }
1083 if( entry )
1084 {
1085 if( type == G_TYPE_BOOLEAN )
5a343ad5 1086 gtk_box_pack_start( GTK_BOX(GTK_DIALOG(dlg)->vbox), entry, FALSE, FALSE, 2 );
bb6d6422
HJYP
1087 else
1088 {
1089 GtkWidget* hbox = gtk_hbox_new( FALSE, 2 );
5a343ad5
JH
1090 gtk_box_pack_start( GTK_BOX(hbox), label, FALSE, FALSE, 2 );
1091 gtk_box_pack_start( GTK_BOX(hbox), entry, TRUE, TRUE, 2 );
1092 gtk_box_pack_start( GTK_BOX(GTK_DIALOG(dlg)->vbox), hbox, FALSE, FALSE, 2 );
bb6d6422
HJYP
1093 }
1094 }
1095 name = va_arg( args, const char* );
1096 }
1097 va_end( args );
04a2f050
HJYP
1098
1099 /* weird... why this doesn't work? */
1100 /* gtk_container_set_border_width( GTK_CONTAINER(GTK_DIALOG(dlg)->vbox), 12 ); */
1101 gtk_container_set_border_width( GTK_CONTAINER(dlg), 8 );
1102
04883e73
HJYP
1103 gtk_widget_show_all( dlg );
1104 return dlg;
bb6d6422
HJYP
1105}
1106
8110399f 1107char* get_config_file( const char* profile, const char* file_name, gboolean is_global )
24053345
HJYP
1108{
1109 char* path;
1110 if( is_global )
1111 {
8110399f 1112 path = g_build_filename( PACKAGE_DATA_DIR, "lxpanel/profile", profile, file_name, NULL );
24053345
HJYP
1113 }
1114 else
1115 {
8110399f 1116 char* dir = g_build_filename( g_get_user_config_dir(), "lxpanel" , profile, NULL);
24053345 1117 /* make sure the private profile dir exists */
8110399f
HJYP
1118 /* FIXME: Should we do this everytime this func gets called?
1119 * Maybe simply doing this before saving config files is enough. */
24053345 1120 g_mkdir_with_parents( dir, 0700 );
8110399f 1121 path = g_build_filename( dir,file_name, NULL);
24053345
HJYP
1122 g_free( dir );
1123 }
1124 return path;
1125}
8110399f 1126
cf701cb7
HJYP
1127const char command_group[] = "Command";
1128void load_global_config()
1129{
1130 GKeyFile* kf = g_key_file_new();
1131 char* file = get_config_file( cprofile, "config", FALSE );
1132 gboolean loaded = g_key_file_load_from_file( kf, file, 0, NULL );
1133 if( ! loaded )
1134 {
1135 g_free( file );
1136 file = get_config_file( cprofile, "config", TRUE ); /* get the system-wide config file */
1137 loaded = g_key_file_load_from_file( kf, file, 0, NULL );
1138 }
1139
1140 if( loaded )
1141 {
1142 file_manager_cmd = g_key_file_get_string( kf, command_group, "FileManager", NULL );
1143 terminal_cmd = g_key_file_get_string( kf, command_group, "Terminal", NULL );
1144 logout_cmd = g_key_file_get_string( kf, command_group, "Logout", NULL );
1145 }
1146 g_key_file_free( kf );
1147}
1148
1149void save_global_config()
1150{
1151 char* file = get_config_file( cprofile, "config", FALSE );
1152 FILE* f = fopen( file, "w" );
1153 if( f )
1154 {
1155 fprintf( f, "[%s]\n", command_group );
1156 if( file_manager_cmd )
1157 fprintf( f, "FileManager=%s\n", file_manager_cmd );
1158 if( terminal_cmd )
1159 fprintf( f, "Terminal=%s\n", terminal_cmd );
1160 if( logout_cmd )
1161 fprintf( f, "Logout=%s\n", logout_cmd );
1162 fclose( f );
1163 }
1164}
1165
1166void free_global_config()
1167{
1168 g_free( file_manager_cmd );
1169 g_free( terminal_cmd );
1170 g_free( logout_cmd );
1171}
1172
1173extern const char*
1174lxpanel_get_file_manager()
1175{
1176 return file_manager_cmd ? file_manager_cmd : "pcmanfm %s";
1177}
1178
1179extern const char*
1180lxpanel_get_terminal()
1181{
1182 return terminal_cmd ? terminal_cmd : "xterm -e";
1183}
1184