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