Use XDG standard paths for fallback (default) settings.
[lxde/lxpanel.git] / src / configurator.c
CommitLineData
16fb8c2e 1/**
18ecfe2a 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
1f4bc3aa
AG
24#define __LXPANEL_INTERNALS__
25
b31cb1d2 26#include "private.h"
a52c2257
HJYP
27#include "misc.h"
28#include "bg.h"
a52c2257
HJYP
29#include <stdlib.h>
30#include <sys/types.h>
31#include <sys/stat.h>
32#include <unistd.h>
33#include <string.h>
e7cb732b 34#include <glib/gi18n.h>
3d6ee560 35#include <libfm/fm-gtk.h>
a52c2257 36
a52c2257
HJYP
37#include "dbg.h"
38
f6881fbf
HJYP
39enum{
40 COL_NAME,
41 COL_EXPAND,
42 COL_DATA,
43 N_COLS
44};
45
4b93d81e 46void panel_configure(Panel* p, int sel_page );
a52c2257 47void restart(void);
08ea5341 48void gtk_run(void);
dd731fde 49void logout(void);
b7629dc7 50static void save_global_config();
a52c2257 51
22242ed4 52Command commands[] = {
8110399f 53 //{ "configure", N_("Preferences"), configure },
ace2a572 54#ifndef DISABLE_MENU
08ea5341 55 { "run", N_("Run"), gtk_run },
ace2a572 56#endif
08ea5341 57 { "restart", N_("Restart"), restart },
389975e0 58 { "logout", N_("Logout"), logout },
a52c2257
HJYP
59 { NULL, NULL },
60};
61
cf701cb7
HJYP
62static char* logout_cmd = NULL;
63
8110399f 64extern GSList* all_panels;
a52c2257 65extern int config;
a52c2257 66
17fab6e5
AG
67/* macros to update config */
68#define UPDATE_GLOBAL_INT(panel,name,val) do { \
69 config_setting_t *_s = config_setting_add(config_setting_get_elem(config_setting_get_member(config_root_setting(panel->config),""),\
70 0),\
71 name,PANEL_CONF_TYPE_INT);\
72 if (_s) config_setting_set_int(_s,val); } while(0)
73
74#define UPDATE_GLOBAL_STRING(panel,name,val) do { \
75 config_setting_t *_s = config_setting_add(config_setting_get_elem(config_setting_get_member(config_root_setting(panel->config),""),\
76 0),\
77 name,PANEL_CONF_TYPE_STRING);\
78 if (_s) config_setting_set_string(_s,val); } while(0)
79
80#define UPDATE_GLOBAL_COLOR(panel,name,val) do { \
81 config_setting_t *_s = config_setting_add(config_setting_get_elem(config_setting_get_member(config_root_setting(panel->config),""),\
82 0),\
83 name,PANEL_CONF_TYPE_INT);\
84 if (_s) { \
85 char _c[8];\
86 snprintf(_c, sizeof(_c), "#%06x",val);\
87 config_setting_set_string(_s,_c); } } while(0)
88
938806f9
RM
89/* GtkColotButton expects a number between 0 and 65535, but p->alpha has range
90 * 0 to 255, and (2^(2n) - 1) / (2^n - 1) = 2^n + 1 = 257, with n = 8. */
91static guint16 const alpha_scale_factor = 257;
92
cf701cb7
HJYP
93void panel_global_config_save( Panel* p, FILE *fp);
94void panel_plugin_config_save( Panel* p, FILE *fp);
a52c2257 95
bee4c26e
HJYP
96static void update_opt_menu(GtkWidget *w, int ind);
97static void update_toggle_button(GtkWidget *w, gboolean n);
389975e0 98static void modify_plugin( GtkTreeView* view );
de569c86 99static gboolean on_entry_focus_out_old( GtkWidget* edit, GdkEventFocus *evt, gpointer user_data );
65a36853 100static gboolean on_entry_focus_out( GtkWidget* edit, GdkEventFocus *evt, gpointer user_data );
de569c86 101static gboolean _on_entry_focus_out_do_work(GtkWidget* edit, gpointer user_data);
bee4c26e 102
a52c2257 103static void
4b93d81e 104response_event(GtkDialog *widget, gint arg1, Panel* panel )
a52c2257 105{
a52c2257 106 switch (arg1) {
bee4c26e
HJYP
107 /* FIXME: what will happen if the user exit lxpanel without
108 close this config dialog?
109 Then the config won't be save, I guess. */
da76d5cf
HJYP
110 case GTK_RESPONSE_DELETE_EVENT:
111 case GTK_RESPONSE_CLOSE:
112 case GTK_RESPONSE_NONE:
cf701cb7 113 panel_config_save( panel );
9c97f69e 114 /* NOTE: NO BREAK HERE*/
3b6661f3 115 gtk_widget_destroy(GTK_WIDGET(widget));
a52c2257
HJYP
116 break;
117 }
4b93d81e 118 return;
a52c2257
HJYP
119}
120
121static void
8110399f 122update_panel_geometry( Panel* p )
bee4c26e 123{
8ed3b3d4 124 /* Guard against being called early in panel creation. */
125 if (p->topgwin != NULL)
126 {
127 calculate_position(p);
128 gtk_widget_set_size_request(p->topgwin, p->aw, p->ah);
129 gdk_window_move(p->topgwin->window, p->ax, p->ay);
130 panel_update_background(p);
131 panel_establish_autohide(p);
132 panel_set_wm_strut(p);
133 }
bee4c26e
HJYP
134}
135
9dd114c4 136static gboolean edge_selector(Panel* p, int edge)
a52c2257 137{
9dd114c4 138 return (p->edge == edge);
139}
04883e73 140
9dd114c4 141/* If there is a panel on this edge and it is not the panel being configured, set the edge unavailable. */
64afc832 142gboolean panel_edge_available(Panel* p, int edge, gint monitor)
9dd114c4 143{
144 GSList* l;
145 for (l = all_panels; l != NULL; l = l->next)
146 {
147 Panel* pl = (Panel*) l->data;
64afc832 148 if ((pl != p) && (pl->edge == edge) && (pl->monitor == monitor))
9dd114c4 149 return FALSE;
150 }
151 return TRUE;
152}
153
154static void set_edge(Panel* p, int edge)
155{
bee4c26e 156 p->edge = edge;
8110399f 157 update_panel_geometry(p);
1d6908fe 158 panel_set_panel_configuration_changed(p);
17fab6e5 159 UPDATE_GLOBAL_STRING(p, "edge", num2str(edge_pair, edge, "none"));
a52c2257
HJYP
160}
161
9dd114c4 162static void edge_bottom_toggle(GtkToggleButton *widget, Panel *p)
a52c2257 163{
9dd114c4 164 if (gtk_toggle_button_get_active(widget))
165 set_edge(p, EDGE_BOTTOM);
166}
04883e73 167
9dd114c4 168static void edge_top_toggle(GtkToggleButton *widget, Panel *p)
169{
170 if (gtk_toggle_button_get_active(widget))
171 set_edge(p, EDGE_TOP);
172}
173
174static void edge_left_toggle(GtkToggleButton *widget, Panel *p)
175{
176 if (gtk_toggle_button_get_active(widget))
177 set_edge(p, EDGE_LEFT);
178}
179
180static void edge_right_toggle(GtkToggleButton *widget, Panel *p)
181{
182 if (gtk_toggle_button_get_active(widget))
183 set_edge(p, EDGE_RIGHT);
184}
185
64afc832
R
186static void set_monitor(GtkAdjustment *widget, Panel *p)
187{
188 p->monitor = gtk_adjustment_get_value(widget);
189 update_panel_geometry(p);
190 panel_set_panel_configuration_changed(p);
17fab6e5 191 UPDATE_GLOBAL_INT(p, "monitor", p->monitor);
64afc832
R
192}
193
9dd114c4 194static void set_alignment(Panel* p, int align)
195{
e7a42ecf 196 if (p->margin_control)
9dd114c4 197 gtk_widget_set_sensitive(p->margin_control, (align != ALLIGN_CENTER));
198 p->allign = align;
8110399f 199 update_panel_geometry(p);
17fab6e5 200 UPDATE_GLOBAL_STRING(p, "allign", num2str(allign_pair, align, "none"));
9dd114c4 201}
202
203static void align_left_toggle(GtkToggleButton *widget, Panel *p)
204{
205 if (gtk_toggle_button_get_active(widget))
206 set_alignment(p, ALLIGN_LEFT);
207}
208
209static void align_center_toggle(GtkToggleButton *widget, Panel *p)
210{
211 if (gtk_toggle_button_get_active(widget))
212 set_alignment(p, ALLIGN_CENTER);
213}
214
215static void align_right_toggle(GtkToggleButton *widget, Panel *p)
216{
217 if (gtk_toggle_button_get_active(widget))
218 set_alignment(p, ALLIGN_RIGHT);
a52c2257
HJYP
219}
220
bee4c26e 221static void
8110399f 222set_margin( GtkSpinButton* spin, Panel* p )
bee4c26e
HJYP
223{
224 p->margin = (int)gtk_spin_button_get_value(spin);
8110399f 225 update_panel_geometry(p);
17fab6e5 226 UPDATE_GLOBAL_INT(p, "margin", p->margin);
bee4c26e
HJYP
227}
228
bee4c26e 229static void
4b93d81e 230set_width( GtkSpinButton* spin, Panel* p )
bee4c26e
HJYP
231{
232 p->width = (int)gtk_spin_button_get_value(spin);
8110399f 233 update_panel_geometry(p);
17fab6e5 234 UPDATE_GLOBAL_INT(p, "width", p->width);
bee4c26e 235}
a52c2257
HJYP
236
237static void
4b93d81e 238set_height( GtkSpinButton* spin, Panel* p )
bee4c26e
HJYP
239{
240 p->height = (int)gtk_spin_button_get_value(spin);
8110399f 241 update_panel_geometry(p);
17fab6e5 242 UPDATE_GLOBAL_INT(p, "height", p->height);
bee4c26e
HJYP
243}
244
f1286efa 245static void set_width_type( GtkWidget *item, Panel* p )
a52c2257 246{
4b93d81e 247 GtkWidget* spin;
a52c2257
HJYP
248 int widthtype;
249 gboolean t;
a52c2257 250 widthtype = gtk_combo_box_get_active(GTK_COMBO_BOX(item)) + 1;
bee4c26e 251 p->widthtype = widthtype;
4b93d81e 252
3b6661f3 253 spin = (GtkWidget*)g_object_get_data(G_OBJECT(item), "width_spin" );
a52c2257 254 t = (widthtype != WIDTH_REQUEST);
4b93d81e 255 gtk_widget_set_sensitive( spin, t );
2918994e 256 if (widthtype == WIDTH_PERCENT)
257 {
7ffaf7a5
HG
258 gtk_spin_button_set_range( GTK_SPIN_BUTTON(spin), 0, 100 );
259 gtk_spin_button_set_value( GTK_SPIN_BUTTON(spin), 100 );
2918994e 260 }
261 else if (widthtype == WIDTH_PIXEL)
262 {
263 if ((p->edge == EDGE_TOP) || (p->edge == EDGE_BOTTOM))
264 {
7ffaf7a5
HG
265 gtk_spin_button_set_range( GTK_SPIN_BUTTON(spin), 0, gdk_screen_width() );
266 gtk_spin_button_set_value( GTK_SPIN_BUTTON(spin), gdk_screen_width() );
2918994e 267 }
268 else
269 {
7ffaf7a5
HG
270 gtk_spin_button_set_range( GTK_SPIN_BUTTON(spin), 0, gdk_screen_height() );
271 gtk_spin_button_set_value( GTK_SPIN_BUTTON(spin), gdk_screen_height() );
2918994e 272 }
a52c2257 273 } else
4b93d81e 274 return;
04883e73 275
8110399f 276 update_panel_geometry(p);
17fab6e5 277 UPDATE_GLOBAL_STRING(p, "widthtype", num2str(width_pair, widthtype, "none"));
a52c2257
HJYP
278}
279
17fab6e5
AG
280/* FIXME: heighttype and spacing and RoundCorners */
281
82ca42af
HG
282static void set_log_level( GtkWidget *cbox, Panel* p)
283{
284 configured_log_level = gtk_combo_box_get_active(GTK_COMBO_BOX(cbox));
285 if (!log_level_set_on_commandline)
286 log_level = configured_log_level;
287 ERR("panel-pref: log level configured to %d, log_level is now %d\n",
288 configured_log_level, log_level);
17fab6e5 289 UPDATE_GLOBAL_INT(p, "loglevel", configured_log_level);
82ca42af
HG
290}
291
f1286efa 292static void transparency_toggle( GtkWidget *b, Panel* p)
a52c2257 293{
3b6661f3 294 GtkWidget* tr = (GtkWidget*)g_object_get_data(G_OBJECT(b), "tint_clr");
f1286efa 295 gboolean t;
a52c2257
HJYP
296
297 ENTER;
faee061a 298
a52c2257 299 t = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b));
faee061a 300 gtk_widget_set_sensitive(tr, t);
4b93d81e 301/*
a52c2257
HJYP
302 gtk_widget_set_sensitive(tr_colorl, t);
303 gtk_widget_set_sensitive(tr_colorb, t);
4b93d81e 304*/
be933927 305 /* Update background immediately. */
6576fd40
FC
306 if (t&&!p->transparent) {
307 p->transparent = 1;
4542c20d 308 p->background = 0;
4542c20d 309 panel_update_background( p );
17fab6e5
AG
310 UPDATE_GLOBAL_INT(p, "transparent", p->transparent);
311 UPDATE_GLOBAL_INT(p, "background", p->background);
368409ba 312 }
a52c2257
HJYP
313 RET();
314}
315
2918994e 316static void background_file_helper(Panel * p, GtkWidget * toggle, GtkFileChooser * file_chooser)
2de71c90 317{
2918994e 318 char * file = g_strdup(gtk_file_chooser_get_filename(file_chooser));
319 if (file != NULL)
320 {
321 g_free(p->background_file);
322 p->background_file = file;
17fab6e5 323 UPDATE_GLOBAL_STRING(p, "backgroundfile", p->background_file);
14f92387 324 }
f1ac64bc 325
2918994e 326 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toggle)))
f1ac64bc 327 {
2918994e 328 if ( ! p->background)
329 {
330 p->transparent = FALSE;
331 p->background = TRUE;
332 panel_update_background(p);
17fab6e5
AG
333 UPDATE_GLOBAL_INT(p, "transparent", p->transparent);
334 UPDATE_GLOBAL_INT(p, "background", p->background);
2918994e 335 }
f1ac64bc 336 }
2918994e 337}
f1ac64bc 338
2918994e 339static void background_toggle( GtkWidget *b, Panel* p)
340{
341 GtkWidget * fc = (GtkWidget*) g_object_get_data(G_OBJECT(b), "img_file");
342 gtk_widget_set_sensitive(fc, gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b)));
343 background_file_helper(p, b, GTK_FILE_CHOOSER(fc));
344}
f1ac64bc 345
2918994e 346static void background_changed(GtkFileChooser *file_chooser, Panel* p )
347{
348 GtkWidget * btn = GTK_WIDGET(g_object_get_data(G_OBJECT(file_chooser), "bg_image"));
349 background_file_helper(p, btn, file_chooser);
2de71c90
FC
350}
351
781afa7b 352static void
8110399f 353background_disable_toggle( GtkWidget *b, Panel* p )
781afa7b
FC
354{
355 ENTER;
356 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b))) {
6576fd40
FC
357 if (p->background!=0||p->transparent!=0) {
358 p->background = 0;
359 p->transparent = 0;
be933927 360 /* Update background immediately. */
4542c20d 361 panel_update_background( p );
17fab6e5
AG
362 UPDATE_GLOBAL_INT(p, "transparent", p->transparent);
363 UPDATE_GLOBAL_INT(p, "background", p->background);
6576fd40 364 }
781afa7b
FC
365 }
366
781afa7b
FC
367 RET();
368}
369
d2669858 370static void
8110399f 371on_font_color_set( GtkColorButton* clr, Panel* p )
d2669858 372{
cf701cb7 373 gtk_color_button_get_color( clr, &p->gfontcolor );
2918994e 374 panel_set_panel_configuration_changed(p);
17fab6e5
AG
375 p->fontcolor = gcolor2rgb24(&p->gfontcolor);
376 UPDATE_GLOBAL_COLOR(p, "fontcolor", p->fontcolor);
d2669858
HJYP
377}
378
cf701cb7 379static void
54d14c9f
MTW
380on_tint_color_set( GtkColorButton* clr, Panel* p )
381{
382 gtk_color_button_get_color( clr, &p->gtintcolor );
e3995304 383 p->tintcolor = gcolor2rgb24(&p->gtintcolor);
938806f9 384 p->alpha = gtk_color_button_get_alpha( clr ) / alpha_scale_factor;
54d14c9f 385 panel_update_background( p );
17fab6e5
AG
386 UPDATE_GLOBAL_COLOR(p, "tintcolor", p->tintcolor);
387 UPDATE_GLOBAL_INT(p, "alpha", p->alpha);
54d14c9f
MTW
388}
389
390static void
8110399f 391on_use_font_color_toggled( GtkToggleButton* btn, Panel* p )
d2669858 392{
3b6661f3 393 GtkWidget* clr = (GtkWidget*)g_object_get_data( G_OBJECT(btn), "clr" );
cf701cb7
HJYP
394 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(btn)))
395 gtk_widget_set_sensitive( clr, TRUE );
396 else
397 gtk_widget_set_sensitive( clr, FALSE );
398 p->usefontcolor = gtk_toggle_button_get_active( btn );
2918994e 399 panel_set_panel_configuration_changed(p);
17fab6e5 400 UPDATE_GLOBAL_INT(p, "usefontcolor", p->usefontcolor);
d2669858
HJYP
401}
402
bee4c26e 403static void
1869ef90
LK
404on_font_size_set( GtkSpinButton* spin, Panel* p )
405{
406 p->fontsize = (int)gtk_spin_button_get_value(spin);
407 panel_set_panel_configuration_changed(p);
17fab6e5 408 UPDATE_GLOBAL_INT(p, "fontsize", p->fontsize);
1869ef90
LK
409}
410
411static void
412on_use_font_size_toggled( GtkToggleButton* btn, Panel* p )
413{
414 GtkWidget* clr = (GtkWidget*)g_object_get_data( G_OBJECT(btn), "clr" );
415 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(btn)))
416 gtk_widget_set_sensitive( clr, TRUE );
417 else
418 gtk_widget_set_sensitive( clr, FALSE );
419 p->usefontsize = gtk_toggle_button_get_active( btn );
420 panel_set_panel_configuration_changed(p);
17fab6e5 421 UPDATE_GLOBAL_INT(p, "usefontsize", p->usefontsize);
1869ef90
LK
422}
423
424
425static void
8110399f 426set_dock_type(GtkToggleButton* toggle, Panel* p )
bee4c26e
HJYP
427{
428 p->setdocktype = gtk_toggle_button_get_active(toggle) ? 1 : 0;
429 panel_set_dock_type( p );
8110399f 430 update_panel_geometry(p);
17fab6e5 431 UPDATE_GLOBAL_INT(p, "setdocktype", p->setdocktype);
bee4c26e
HJYP
432}
433
434static void
176fb687 435set_strut(GtkToggleButton* toggle, Panel* p )
bee4c26e
HJYP
436{
437 p->setstrut = gtk_toggle_button_get_active(toggle) ? 1 : 0;
8110399f 438 update_panel_geometry(p);
17fab6e5 439 UPDATE_GLOBAL_INT(p, "setpartialstrut", p->setstrut);
bee4c26e
HJYP
440}
441
ce522551 442static void
176fb687 443set_autohide(GtkToggleButton* toggle, Panel* p )
444{
445 p->autohide = gtk_toggle_button_get_active(toggle) ? 1 : 0;
446 update_panel_geometry(p);
17fab6e5 447 UPDATE_GLOBAL_INT(p, "autohide", p->autohide);
176fb687 448}
449
450static void
451set_height_when_minimized( GtkSpinButton* spin, Panel* p )
452{
453 p->height_when_hidden = (int)gtk_spin_button_get_value(spin);
454 update_panel_geometry(p);
17fab6e5 455 UPDATE_GLOBAL_INT(p, "heightwhenhidden", p->height_when_hidden);
176fb687 456}
457
458static void
8f9e6256 459set_icon_size( GtkSpinButton* spin, Panel* p )
460{
461 p->icon_size = (int)gtk_spin_button_get_value(spin);
462 panel_set_panel_configuration_changed(p);
17fab6e5 463 UPDATE_GLOBAL_INT(p, "iconsize", p->icon_size);
8f9e6256 464}
465
466static void
04883e73 467on_sel_plugin_changed( GtkTreeSelection* tree_sel, GtkWidget* label )
a52c2257 468{
8ccd023a
HJYP
469 GtkTreeIter it;
470 GtkTreeModel* model;
17fab6e5 471 GtkWidget* pl;
a52c2257 472
8ccd023a
HJYP
473 if( gtk_tree_selection_get_selected( tree_sel, &model, &it ) )
474 {
cfc83537 475 GtkTreeView* view = gtk_tree_selection_get_tree_view( tree_sel );
5a343ad5 476 GtkWidget *edit_btn = GTK_WIDGET(g_object_get_data( G_OBJECT(view), "edit_btn" ));
17fab6e5 477 LXPanelPluginInit *init;
f6881fbf 478 gtk_tree_model_get( model, &it, COL_DATA, &pl, -1 );
17fab6e5
AG
479 init = PLUGIN_CLASS(pl);
480 gtk_label_set_text( GTK_LABEL(label), _(init->description) );
481 gtk_widget_set_sensitive( edit_btn, init->config != NULL );
8ccd023a 482 }
ce522551 483}
a52c2257 484
f6881fbf
HJYP
485static void
486on_plugin_expand_toggled(GtkCellRendererToggle* render, char* path, GtkTreeView* view)
487{
488 GtkTreeModel* model;
489 GtkTreeIter it;
490 GtkTreePath* tp = gtk_tree_path_new_from_string( path );
491 model = gtk_tree_view_get_model( view );
492 if( gtk_tree_model_get_iter( model, &it, tp ) )
493 {
17fab6e5 494 GtkWidget* pl;
f6881fbf 495 gboolean old_expand, expand, fill;
18ecfe2a 496 guint padding;
f6881fbf 497 GtkPackType pack_type;
17fab6e5
AG
498 LXPanelPluginInit *init;
499 Panel *panel;
f6881fbf
HJYP
500
501 gtk_tree_model_get( model, &it, COL_DATA, &pl, COL_EXPAND, &expand, -1 );
17fab6e5
AG
502 init = PLUGIN_CLASS(pl);
503 panel = PLUGIN_PANEL(pl);
f6881fbf 504
17fab6e5 505 if (init->expand_available)
2918994e 506 {
b8474715 507 config_setting_t *s = g_object_get_qdata(G_OBJECT(pl), lxpanel_plugin_qconf);
2918994e 508 /* Only honor "stretch" if allowed by the plugin. */
509 expand = ! expand;
7ffaf7a5 510 gtk_list_store_set( GTK_LIST_STORE(model), &it, COL_EXPAND, expand, -1 );
2918994e 511
512 /* Query the old packing of the plugin widget.
513 * Apply the new packing with only "expand" modified. */
17fab6e5
AG
514 gtk_box_query_child_packing( GTK_BOX(panel->box), pl, &old_expand, &fill, &padding, &pack_type );
515 gtk_box_set_child_packing( GTK_BOX(panel->box), pl, expand, fill, padding, pack_type );
b8474715 516 if (expand)
a8d4af54 517 config_group_set_int(s, "expand", 1);
b8474715
AG
518 else
519 config_setting_remove(s, "expand");
2918994e 520 }
f6881fbf
HJYP
521 }
522 gtk_tree_path_free( tp );
523}
524
2918994e 525static void on_stretch_render(GtkTreeViewColumn * column, GtkCellRenderer * renderer, GtkTreeModel * model, GtkTreeIter * iter, gpointer data)
526{
527 /* Set the control visible depending on whether stretch is available for the plugin.
528 * The g_object_set method is touchy about its parameter, so we can't pass the boolean directly. */
17fab6e5 529 GtkWidget * pl;
2918994e 530 gtk_tree_model_get(model, iter, COL_DATA, &pl, -1);
531 g_object_set(renderer,
17fab6e5 532 "visible", ((PLUGIN_CLASS(pl)->expand_available) ? TRUE : FALSE),
2918994e 533 NULL);
534}
535
8110399f 536static void init_plugin_list( Panel* p, GtkTreeView* view, GtkWidget* label )
ce522551 537{
ce522551
HJYP
538 GtkListStore* list;
539 GtkTreeViewColumn* col;
540 GtkCellRenderer* render;
541 GtkTreeSelection* tree_sel;
17fab6e5 542 GList *plugins, *l;
8ccd023a 543 GtkTreeIter it;
ce522551 544
3b6661f3 545 g_object_set_data( G_OBJECT(view), "panel", p );
8110399f 546
ce522551
HJYP
547 render = gtk_cell_renderer_text_new();
548 col = gtk_tree_view_column_new_with_attributes(
549 _("Currently loaded plugins"),
f6881fbf
HJYP
550 render, "text", COL_NAME, NULL );
551 gtk_tree_view_column_set_expand( col, TRUE );
552 gtk_tree_view_append_column( view, col );
553
554 render = gtk_cell_renderer_toggle_new();
555 g_object_set( render, "activatable", TRUE, NULL );
556 g_signal_connect( render, "toggled", G_CALLBACK( on_plugin_expand_toggled ), view );
557 col = gtk_tree_view_column_new_with_attributes(
558 _("Stretch"),
559 render, "active", COL_EXPAND, NULL );
560 gtk_tree_view_column_set_expand( col, FALSE );
2918994e 561 gtk_tree_view_column_set_cell_data_func(col, render, on_stretch_render, NULL, NULL);
ce522551
HJYP
562 gtk_tree_view_append_column( view, col );
563
f6881fbf 564 list = gtk_list_store_new( N_COLS, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_POINTER );
17fab6e5
AG
565 plugins = gtk_container_get_children(GTK_CONTAINER(p->box));
566 for( l = plugins; l; l = l->next )
ce522551
HJYP
567 {
568 GtkTreeIter it;
17fab6e5
AG
569 gboolean expand;
570 GtkWidget *w = (GtkWidget*)l->data;
571 gtk_container_child_get(GTK_CONTAINER(p->box), w, "expand", &expand, NULL);
ce522551
HJYP
572 gtk_list_store_append( list, &it );
573 gtk_list_store_set( list, &it,
17fab6e5
AG
574 COL_NAME, _(PLUGIN_CLASS(w)->name),
575 COL_EXPAND, expand,
576 COL_DATA, w,
2918994e 577 -1);
ce522551 578 }
17fab6e5 579 g_list_free(plugins);
ce522551 580 gtk_tree_view_set_model( view, GTK_TREE_MODEL( list ) );
389975e0
HJYP
581 g_signal_connect( view, "row-activated",
582 G_CALLBACK(modify_plugin), NULL );
ce522551 583 tree_sel = gtk_tree_view_get_selection( view );
16fb8c2e 584 gtk_tree_selection_set_mode( tree_sel, GTK_SELECTION_BROWSE );
ce522551 585 g_signal_connect( tree_sel, "changed",
04883e73 586 G_CALLBACK(on_sel_plugin_changed), label);
8ccd023a
HJYP
587 if( gtk_tree_model_get_iter_first( GTK_TREE_MODEL(list), &it ) )
588 gtk_tree_selection_select_iter( tree_sel, &it );
ce522551
HJYP
589}
590
a3743567
JL
591static void on_add_plugin_row_activated( GtkTreeView *tree_view,
592 GtkTreePath *path,
593 GtkTreeViewColumn *col,
594 gpointer user_data)
595{
596 GtkWidget *dlg;
597
598 dlg = (GtkWidget *) user_data;
599
600 (void) tree_view;
601 (void) path;
602 (void) col;
603
604 /* Emitting the "response" signal ourselves. */
605 gtk_dialog_response(GTK_DIALOG(dlg), GTK_RESPONSE_OK);
606}
607
16fb8c2e
HJYP
608static void on_add_plugin_response( GtkDialog* dlg,
609 int response,
610 GtkTreeView* _view )
ce522551 611{
3b6661f3 612 Panel* p = (Panel*) g_object_get_data( G_OBJECT(_view), "panel" );
16fb8c2e
HJYP
613 if( response == GTK_RESPONSE_OK )
614 {
615 GtkTreeView* view;
616 GtkTreeSelection* tree_sel;
617 GtkTreeIter it;
618 GtkTreeModel* model;
619
67e88af2 620 view = (GtkTreeView*)g_object_get_data( G_OBJECT(dlg), "avail-plugins" );
16fb8c2e
HJYP
621 tree_sel = gtk_tree_view_get_selection( view );
622 if( gtk_tree_selection_get_selected( tree_sel, &model, &it ) )
623 {
624 char* type = NULL;
17fab6e5
AG
625 GtkWidget *pl;
626 config_setting_t *cfg;
da46ec64
AG
627
628 cfg = config_group_add_subgroup(config_root_setting(p->config),
629 "Plugin");
366cf5fe 630 gtk_tree_model_get( model, &it, 1, &type, -1 );
da46ec64 631 config_group_set_string(cfg, "type", type);
17fab6e5 632 if ((pl = lxpanel_add_plugin(p, type, cfg, -1)))
16fb8c2e 633 {
1d0f0857 634 GtkTreePath* tree_path;
17fab6e5 635 gboolean expand;
1d0f0857 636
60c77f70
MJ
637 panel_config_save(p);
638
17fab6e5
AG
639 plugin_widget_set_background(pl, p);
640 gtk_container_child_get(GTK_CONTAINER(p->box), pl, "expand", &expand, NULL);
1d0f0857 641 model = gtk_tree_view_get_model( _view );
7ffaf7a5
HG
642 gtk_list_store_append( GTK_LIST_STORE(model), &it );
643 gtk_list_store_set( GTK_LIST_STORE(model), &it,
17fab6e5
AG
644 COL_NAME, _(PLUGIN_CLASS(pl)->name),
645 COL_EXPAND, expand,
f6881fbf 646 COL_DATA, pl, -1 );
1d0f0857
HJYP
647 tree_sel = gtk_tree_view_get_selection( _view );
648 gtk_tree_selection_select_iter( tree_sel, &it );
18ecfe2a 649 if ((tree_path = gtk_tree_model_get_path(model, &it)) != NULL)
1d0f0857
HJYP
650 {
651 gtk_tree_view_scroll_to_cell( _view, tree_path, NULL, FALSE, 0, 0 );
652 gtk_tree_path_free( tree_path );
653 }
16fb8c2e 654 }
17fab6e5
AG
655 else /* free unused setting */
656 config_setting_destroy(cfg);
16fb8c2e
HJYP
657 g_free( type );
658 }
659 }
7ffaf7a5 660 gtk_widget_destroy( GTK_WIDGET(dlg) );
16fb8c2e
HJYP
661}
662
663static void on_add_plugin( GtkButton* btn, GtkTreeView* _view )
664{
665 GtkWidget* dlg, *parent_win, *scroll;
17fab6e5 666 GHashTable *classes;
16fb8c2e
HJYP
667 GtkTreeViewColumn* col;
668 GtkCellRenderer* render;
669 GtkTreeView* view;
670 GtkListStore* list;
671 GtkTreeSelection* tree_sel;
17fab6e5
AG
672 GHashTableIter iter;
673 gpointer key, val;
16fb8c2e 674
3b6661f3 675 Panel* p = (Panel*) g_object_get_data( G_OBJECT(_view), "panel" );
8110399f 676
17fab6e5 677 classes = lxpanel_get_all_types();
16fb8c2e 678
7ffaf7a5 679 parent_win = gtk_widget_get_toplevel( GTK_WIDGET(_view) );
16fb8c2e 680 dlg = gtk_dialog_new_with_buttons( _("Add plugin to panel"),
67e88af2 681 GTK_WINDOW(parent_win), 0,
16fb8c2e
HJYP
682 GTK_STOCK_CANCEL,
683 GTK_RESPONSE_CANCEL,
684 GTK_STOCK_ADD,
685 GTK_RESPONSE_OK, NULL );
e7a42ecf 686 panel_apply_icon(GTK_WINDOW(dlg));
5420dd00
FC
687
688 /* fix background */
5b6ce65c
FC
689 if (p->background)
690 gtk_widget_set_style(dlg, p->defstyle);
5420dd00 691
1d0f0857 692 /* gtk_widget_set_sensitive( parent_win, FALSE ); */
16fb8c2e 693 scroll = gtk_scrolled_window_new( NULL, NULL );
7ffaf7a5 694 gtk_scrolled_window_set_shadow_type( GTK_SCROLLED_WINDOW(scroll),
16fb8c2e 695 GTK_SHADOW_IN );
7ffaf7a5 696 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll),
16fb8c2e
HJYP
697 GTK_POLICY_AUTOMATIC,
698 GTK_POLICY_AUTOMATIC );
7ffaf7a5 699 gtk_box_pack_start( GTK_BOX(GTK_DIALOG(dlg)->vbox), scroll,
16fb8c2e 700 TRUE, TRUE, 4 );
7ffaf7a5
HG
701 view = GTK_TREE_VIEW(gtk_tree_view_new());
702 gtk_container_add( GTK_CONTAINER(scroll), GTK_WIDGET(view) );
16fb8c2e
HJYP
703 tree_sel = gtk_tree_view_get_selection( view );
704 gtk_tree_selection_set_mode( tree_sel, GTK_SELECTION_BROWSE );
705
706 render = gtk_cell_renderer_text_new();
707 col = gtk_tree_view_column_new_with_attributes(
708 _("Available plugins"),
709 render, "text", 0, NULL );
710 gtk_tree_view_append_column( view, col );
711
712 list = gtk_list_store_new( 2,
713 G_TYPE_STRING,
714 G_TYPE_STRING );
715
9dd114c4 716 /* Populate list of available plugins.
717 * Omit plugins that can only exist once per system if it is already configured. */
17fab6e5
AG
718 g_hash_table_iter_init(&iter, classes);
719 while(g_hash_table_iter_next(&iter, &key, &val))
720 {
721 register LXPanelPluginInit *init = val;
ae4e6dc6
AG
722 if (init->superseded)
723 continue;
10d93053 724 if (!init->one_per_system || !_class_is_present(init))
9dd114c4 725 {
16fb8c2e
HJYP
726 GtkTreeIter it;
727 gtk_list_store_append( list, &it );
17fab6e5 728 /* it is safe to put classes data here - they will be valid until restart */
16fb8c2e 729 gtk_list_store_set( list, &it,
17fab6e5
AG
730 0, _(init->name),
731 1, key,
2918994e 732 -1 );
16fb8c2e
HJYP
733 /* g_debug( "%s (%s)", pc->type, _(pc->name) ); */
734 }
6a6ad54e 735 }
16fb8c2e
HJYP
736
737 gtk_tree_view_set_model( view, GTK_TREE_MODEL(list) );
738 g_object_unref( list );
739
a3743567
JL
740 /*
741 * The user can add a plugin either by clicking the "Add" button, or by
742 * double-clicking the plugin.
743 */
16fb8c2e 744 g_signal_connect( dlg, "response",
8dfd6a73 745 G_CALLBACK(on_add_plugin_response), _view );
a3743567
JL
746 g_signal_connect( view, "row-activated",
747 G_CALLBACK(on_add_plugin_row_activated), (gpointer) dlg);
748
3b6661f3 749 g_object_set_data( G_OBJECT(dlg), "avail-plugins", view );
16fb8c2e 750
7ffaf7a5 751 gtk_window_set_default_size( GTK_WINDOW(dlg), 320, 400 );
16fb8c2e 752 gtk_widget_show_all( dlg );
ce522551
HJYP
753}
754
04883e73 755static void on_remove_plugin( GtkButton* btn, GtkTreeView* view )
ce522551 756{
8ccd023a
HJYP
757 GtkTreeIter it;
758 GtkTreePath* tree_path;
759 GtkTreeModel* model;
760 GtkTreeSelection* tree_sel = gtk_tree_view_get_selection( view );
17fab6e5 761 GtkWidget* pl;
ce522551 762
3b6661f3 763 Panel* p = (Panel*) g_object_get_data( G_OBJECT(view), "panel" );
8110399f 764
8ccd023a
HJYP
765 if( gtk_tree_selection_get_selected( tree_sel, &model, &it ) )
766 {
767 tree_path = gtk_tree_model_get_path( model, &it );
f6881fbf 768 gtk_tree_model_get( model, &it, COL_DATA, &pl, -1 );
8ccd023a
HJYP
769 if( gtk_tree_path_get_indices(tree_path)[0] >= gtk_tree_model_iter_n_children( model, NULL ) )
770 gtk_tree_path_prev( tree_path );
771 gtk_list_store_remove( GTK_LIST_STORE(model), &it );
8bf045c9
MJ
772 gtk_tree_selection_select_path( tree_sel, tree_path );
773 gtk_tree_path_free( tree_path );
774
17fab6e5
AG
775 config_setting_destroy(g_object_get_qdata(G_OBJECT(pl), lxpanel_plugin_qconf));
776 /* reset conf pointer because the widget still may be referenced by configurator */
777 g_object_set_qdata(G_OBJECT(pl), lxpanel_plugin_qconf, NULL);
778 gtk_widget_destroy(pl);
60c77f70 779 panel_config_save(p);
8ccd023a 780 }
ce522551
HJYP
781}
782
389975e0 783void modify_plugin( GtkTreeView* view )
04883e73
HJYP
784{
785 GtkTreeSelection* tree_sel = gtk_tree_view_get_selection( view );
786 GtkTreeModel* model;
787 GtkTreeIter it;
17fab6e5
AG
788 GtkWidget* pl;
789 LXPanelPluginInit *init;
04883e73
HJYP
790
791 if( ! gtk_tree_selection_get_selected( tree_sel, &model, &it ) )
792 return;
793
f6881fbf 794 gtk_tree_model_get( model, &it, COL_DATA, &pl, -1 );
17fab6e5
AG
795 init = PLUGIN_CLASS(pl);
796 if (init->config)
131514c9
AG
797 {
798 GtkWidget *dlg;
799 Panel *panel = PLUGIN_PANEL(pl);
800 dlg = init->config(panel, pl, GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(view))));
801 if (dlg)
802 _panel_show_config_dialog(panel, pl, dlg);
803 }
04883e73
HJYP
804}
805
17fab6e5 806static int get_widget_index(Panel* p, GtkWidget* pl)
ce522551 807{
17fab6e5
AG
808 GList *plugins = gtk_container_get_children(GTK_CONTAINER(p->box));
809 int i = g_list_index(plugins, pl);
810 g_list_free(plugins);
811 return i;
ce522551
HJYP
812}
813
814static void on_moveup_plugin( GtkButton* btn, GtkTreeView* view )
815{
ce522551
HJYP
816 GtkTreeIter it, prev;
817 GtkTreeModel* model = gtk_tree_view_get_model( view );
818 GtkTreeSelection* tree_sel = gtk_tree_view_get_selection( view );
819 int i;
820
3b6661f3 821 Panel* panel = (Panel*) g_object_get_data( G_OBJECT(view), "panel" );
8110399f 822
ce522551
HJYP
823 if( ! gtk_tree_model_get_iter_first( model, &it ) )
824 return;
825 if( gtk_tree_selection_iter_is_selected( tree_sel, &it ) )
826 return;
827 do{
828 if( gtk_tree_selection_iter_is_selected(tree_sel, &it) )
829 {
17fab6e5
AG
830 GtkWidget* pl;
831 config_setting_t *s;
f6881fbf 832 gtk_tree_model_get( model, &it, COL_DATA, &pl, -1 );
ce522551
HJYP
833 gtk_list_store_move_before( GTK_LIST_STORE( model ),
834 &it, &prev );
835
17fab6e5
AG
836 i = get_widget_index(panel, pl);
837 s = g_object_get_qdata(G_OBJECT(pl), lxpanel_plugin_qconf);
838 /* reorder in config, 0 is Global */
f9e8104e
AG
839 if (i == 0)
840 i = 1;
17fab6e5
AG
841 config_setting_move_elem(s, config_setting_get_parent(s), i);
842 /* reorder in panel */
843 gtk_box_reorder_child(GTK_BOX(panel->box), pl, i - 1);
60c77f70 844 panel_config_save(panel);
ce522551
HJYP
845 return;
846 }
847 prev = it;
848 }while( gtk_tree_model_iter_next( model, &it ) );
849}
850
851static void on_movedown_plugin( GtkButton* btn, GtkTreeView* view )
852{
ce522551
HJYP
853 GtkTreeIter it, next;
854 GtkTreeModel* model;
855 GtkTreeSelection* tree_sel = gtk_tree_view_get_selection( view );
17fab6e5
AG
856 GtkWidget* pl;
857 config_setting_t *s;
ce522551
HJYP
858 int i;
859
3b6661f3 860 Panel* panel = (Panel*) g_object_get_data( G_OBJECT(view), "panel" );
8110399f 861
ce522551
HJYP
862 if( ! gtk_tree_selection_get_selected( tree_sel, &model, &it ) )
863 return;
864 next = it;
865
866 if( ! gtk_tree_model_iter_next( model, &next) )
867 return;
868
f6881fbf 869 gtk_tree_model_get( model, &it, COL_DATA, &pl, -1 );
ce522551
HJYP
870
871 gtk_list_store_move_after( GTK_LIST_STORE( model ), &it, &next );
872
17fab6e5
AG
873 i = get_widget_index(panel, pl) + 1;
874 s = g_object_get_qdata(G_OBJECT(pl), lxpanel_plugin_qconf);
875 /* reorder in config, 0 is Global */
876 config_setting_move_elem(s, config_setting_get_parent(s), i + 1);
877 /* reorder in panel */
878 gtk_box_reorder_child(GTK_BOX(panel->box), pl, i);
60c77f70 879 panel_config_save(panel);
ce522551
HJYP
880}
881
a52c2257
HJYP
882static void
883update_opt_menu(GtkWidget *w, int ind)
884{
885 int i;
886
887 ENTER;
888 /* this trick will trigger "changed" signal even if active entry is
889 * not actually changing */
890 i = gtk_combo_box_get_active(GTK_COMBO_BOX(w));
891 if (i == ind) {
892 i = i ? 0 : 1;
893 gtk_combo_box_set_active(GTK_COMBO_BOX(w), i);
894 }
895 gtk_combo_box_set_active(GTK_COMBO_BOX(w), ind);
896 RET();
897}
898
899static void
900update_toggle_button(GtkWidget *w, gboolean n)
901{
902 gboolean c;
903
904 ENTER;
905 /* this trick will trigger "changed" signal even if active entry is
906 * not actually changing */
907 c = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w));
908 if (c == n) {
909 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), !n);
910 }
911 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), n);
912 RET();
913}
914
8dfa5918
AG
915static void on_app_chooser_destroy(GtkComboBox *fm, gpointer _unused)
916{
917 gboolean is_changed;
918 GAppInfo *app = fm_app_chooser_combo_box_dup_selected_app(fm, &is_changed);
919 if(app)
920 {
921 if(is_changed)
922 g_app_info_set_as_default_for_type(app, "inode/directory", NULL);
923 g_object_unref(app);
924 }
925}
926
f1286efa 927void panel_configure( Panel* p, int sel_page )
a52c2257 928{
f1286efa 929 GtkBuilder* builder;
18ecfe2a 930 GtkWidget *w, *w2, *tint_clr;
8dfa5918
AG
931 FmMimeType *mt;
932 GtkComboBox *fm;
64afc832
R
933 GdkScreen *screen;
934 gint monitors;
4b93d81e
HJYP
935
936 if( p->pref_dialog )
937 {
9dd114c4 938 panel_adjust_geometry_terminology(p);
176fb687 939 gtk_window_present(GTK_WINDOW(p->pref_dialog));
4b93d81e
HJYP
940 return;
941 }
88d364eb 942
f1286efa 943 builder = gtk_builder_new();
43fedc4f 944 if( !gtk_builder_add_from_file(builder, PACKAGE_UI_DIR "/panel-pref.ui", NULL) )
f1286efa
HJYP
945 {
946 g_object_unref(builder);
947 return;
948 }
949
950 p->pref_dialog = (GtkWidget*)gtk_builder_get_object( builder, "panel_pref" );
7ffaf7a5 951 g_signal_connect(p->pref_dialog, "response", G_CALLBACK(response_event), p);
e7a42ecf 952 g_object_add_weak_pointer( G_OBJECT(p->pref_dialog), (gpointer) &p->pref_dialog );
7ffaf7a5 953 gtk_window_set_position( GTK_WINDOW(p->pref_dialog), GTK_WIN_POS_CENTER );
e7a42ecf 954 panel_apply_icon(GTK_WINDOW(p->pref_dialog));
4b93d81e 955
4b93d81e 956 /* position */
9dd114c4 957 w = (GtkWidget*)gtk_builder_get_object( builder, "edge_bottom" );
958 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), edge_selector(p, EDGE_BOTTOM));
9dd114c4 959 g_signal_connect(w, "toggled", G_CALLBACK(edge_bottom_toggle), p);
960 w = (GtkWidget*)gtk_builder_get_object( builder, "edge_top" );
961 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), edge_selector(p, EDGE_TOP));
9dd114c4 962 g_signal_connect(w, "toggled", G_CALLBACK(edge_top_toggle), p);
963 w = (GtkWidget*)gtk_builder_get_object( builder, "edge_left" );
964 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), edge_selector(p, EDGE_LEFT));
9dd114c4 965 g_signal_connect(w, "toggled", G_CALLBACK(edge_left_toggle), p);
966 w = (GtkWidget*)gtk_builder_get_object( builder, "edge_right" );
967 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), edge_selector(p, EDGE_RIGHT));
9dd114c4 968 g_signal_connect(w, "toggled", G_CALLBACK(edge_right_toggle), p);
969
64afc832
R
970 /* monitor */
971 monitors = 1;
972 screen = gdk_screen_get_default();
973 if(screen) monitors = gdk_screen_get_n_monitors(screen);
974 g_assert(monitors >= 1);
975 w = (GtkWidget*)gtk_builder_get_object( builder, "monitor" );
976 gtk_spin_button_set_value(GTK_SPIN_BUTTON(w), p->monitor + 1);
977 gtk_spin_button_set_range(GTK_SPIN_BUTTON(w), 1, monitors);
978 gtk_widget_set_sensitive(w, monitors > 1);
979 g_signal_connect(w, "value-changed", G_CALLBACK(set_monitor), p);
980
9dd114c4 981 /* alignment */
2918994e 982 p->alignment_left_label = w = (GtkWidget*)gtk_builder_get_object( builder, "alignment_left" );
9dd114c4 983 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), (p->allign == ALLIGN_LEFT));
984 g_signal_connect(w, "toggled", G_CALLBACK(align_left_toggle), p);
985 w = (GtkWidget*)gtk_builder_get_object( builder, "alignment_center" );
986 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), (p->allign == ALLIGN_CENTER));
987 g_signal_connect(w, "toggled", G_CALLBACK(align_center_toggle), p);
2918994e 988 p->alignment_right_label = w = (GtkWidget*)gtk_builder_get_object( builder, "alignment_right" );
9dd114c4 989 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), (p->allign == ALLIGN_RIGHT));
2918994e 990 g_signal_connect(w, "toggled", G_CALLBACK(align_right_toggle), p);
9dd114c4 991
992 /* margin */
e7a42ecf 993 p->margin_control = w = (GtkWidget*)gtk_builder_get_object( builder, "margin" );
7ffaf7a5 994 gtk_spin_button_set_value(GTK_SPIN_BUTTON(w), p->margin);
e7a42ecf 995 gtk_widget_set_sensitive(p->margin_control, (p->allign != ALLIGN_CENTER));
4b93d81e
HJYP
996 g_signal_connect( w, "value-changed",
997 G_CALLBACK(set_margin), p);
998
999 /* size */
9dd114c4 1000 p->width_label = (GtkWidget*)gtk_builder_get_object( builder, "width_label");
2918994e 1001 p->width_control = w = (GtkWidget*)gtk_builder_get_object( builder, "width" );
4b93d81e 1002 gtk_widget_set_sensitive( w, p->widthtype != WIDTH_REQUEST );
e7a42ecf 1003 gint upper = 0;
2918994e 1004 if( p->widthtype == WIDTH_PERCENT)
e7a42ecf 1005 upper = 100;
2918994e 1006 else if( p->widthtype == WIDTH_PIXEL)
1007 upper = (((p->edge == EDGE_TOP) || (p->edge == EDGE_BOTTOM)) ? gdk_screen_width() : gdk_screen_height());
7ffaf7a5
HG
1008 gtk_spin_button_set_range( GTK_SPIN_BUTTON(w), 0, upper );
1009 gtk_spin_button_set_value( GTK_SPIN_BUTTON(w), p->width );
4b93d81e
HJYP
1010 g_signal_connect( w, "value-changed", G_CALLBACK(set_width), p );
1011
f1286efa 1012 w = (GtkWidget*)gtk_builder_get_object( builder, "width_unit" );
4b93d81e 1013 update_opt_menu( w, p->widthtype - 1 );
2918994e 1014 g_object_set_data(G_OBJECT(w), "width_spin", p->width_control );
4b93d81e
HJYP
1015 g_signal_connect( w, "changed",
1016 G_CALLBACK(set_width_type), p);
1017
9dd114c4 1018 p->height_label = (GtkWidget*)gtk_builder_get_object( builder, "height_label");
1019 p->height_control = w = (GtkWidget*)gtk_builder_get_object( builder, "height" );
7ffaf7a5
HG
1020 gtk_spin_button_set_range( GTK_SPIN_BUTTON(w), PANEL_HEIGHT_MIN, PANEL_HEIGHT_MAX );
1021 gtk_spin_button_set_value( GTK_SPIN_BUTTON(w), p->height );
4b93d81e
HJYP
1022 g_signal_connect( w, "value-changed", G_CALLBACK(set_height), p );
1023
f1286efa 1024 w = (GtkWidget*)gtk_builder_get_object( builder, "height_unit" );
4b93d81e 1025 update_opt_menu( w, HEIGHT_PIXEL - 1);
8f9e6256 1026
1027 w = (GtkWidget*)gtk_builder_get_object( builder, "icon_size" );
7ffaf7a5
HG
1028 gtk_spin_button_set_range( GTK_SPIN_BUTTON(w), PANEL_HEIGHT_MIN, PANEL_HEIGHT_MAX );
1029 gtk_spin_button_set_value( GTK_SPIN_BUTTON(w), p->icon_size );
93a217b3 1030 g_signal_connect( w, "value-changed", G_CALLBACK(set_icon_size), p );
4b93d81e
HJYP
1031
1032 /* properties */
1033
1034 /* Explaination from Ruediger Arp <ruediger@gmx.net>:
1035 "Set Dock Type", it is referring to the behaviour of
1036 dockable applications such as those found in WindowMaker (e.g.
1037 http://www.cs.mun.ca/~gstarkes/wmaker/dockapps ) and other
1038 lightweight window managers. These dockapps are probably being
1039 treated in some special way.
1040 */
f1286efa 1041 w = (GtkWidget*)gtk_builder_get_object( builder, "as_dock" );
4b93d81e
HJYP
1042 update_toggle_button( w, p->setdocktype );
1043 g_signal_connect( w, "toggled",
1044 G_CALLBACK(set_dock_type), p );
1045
1046 /* Explaination from Ruediger Arp <ruediger@gmx.net>:
1047 "Set Strut": Reserve panel's space so that it will not be
1048 covered by maximazied windows.
1049 This is clearly an option to avoid the panel being
1050 covered/hidden by other applications so that it always is
1051 accessible. The panel "steals" some screen estate which cannot
1052 be accessed by other applications.
1053 GNOME Panel acts this way, too.
1054 */
f1286efa 1055 w = (GtkWidget*)gtk_builder_get_object( builder, "reserve_space" );
4b93d81e
HJYP
1056 update_toggle_button( w, p->setstrut );
1057 g_signal_connect( w, "toggled",
176fb687 1058 G_CALLBACK(set_strut), p );
1059
1060 w = (GtkWidget*)gtk_builder_get_object( builder, "autohide" );
1061 update_toggle_button( w, p->autohide );
1062 g_signal_connect( w, "toggled",
1063 G_CALLBACK(set_autohide), p );
1064
1065 w = (GtkWidget*)gtk_builder_get_object( builder, "height_when_minimized" );
1066 gtk_spin_button_set_value(GTK_SPIN_BUTTON(w), p->height_when_hidden);
1067 g_signal_connect( w, "value-changed",
1068 G_CALLBACK(set_height_when_minimized), p);
4b93d81e
HJYP
1069
1070 /* transparancy */
f1286efa 1071 tint_clr = w = (GtkWidget*)gtk_builder_get_object( builder, "tint_clr" );
7ffaf7a5
HG
1072 gtk_color_button_set_color(GTK_COLOR_BUTTON(w), &p->gtintcolor);
1073 gtk_color_button_set_alpha(GTK_COLOR_BUTTON(w), alpha_scale_factor * p->alpha);
4b93d81e
HJYP
1074 if ( ! p->transparent )
1075 gtk_widget_set_sensitive( w, FALSE );
54d14c9f 1076 g_signal_connect( w, "color-set", G_CALLBACK( on_tint_color_set ), p );
4b93d81e
HJYP
1077
1078 /* background */
1079 {
1080 GtkWidget* none, *trans, *img;
bbf224a4 1081 GtkIconInfo* info;
f1286efa
HJYP
1082 none = (GtkWidget*)gtk_builder_get_object( builder, "bg_none" );
1083 trans = (GtkWidget*)gtk_builder_get_object( builder, "bg_transparency" );
1084 img = (GtkWidget*)gtk_builder_get_object( builder, "bg_image" );
4b93d81e 1085
3b6661f3 1086 g_object_set_data(G_OBJECT(trans), "tint_clr", tint_clr);
4b93d81e
HJYP
1087
1088 if (p->background)
7ffaf7a5 1089 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(img), TRUE);
4b93d81e 1090 else if (p->transparent)
7ffaf7a5 1091 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(trans), TRUE);
4b93d81e 1092 else
7ffaf7a5 1093 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(none), TRUE);
4b93d81e
HJYP
1094
1095 g_signal_connect(none, "toggled", G_CALLBACK(background_disable_toggle), p);
1096 g_signal_connect(trans, "toggled", G_CALLBACK(transparency_toggle), p);
1097 g_signal_connect(img, "toggled", G_CALLBACK(background_toggle), p);
1098
2918994e 1099 w = (GtkWidget*)gtk_builder_get_object( builder, "img_file" );
1100 g_object_set_data(G_OBJECT(img), "img_file", w);
bbf224a4
AG
1101 if (p->background_file != NULL)
1102 gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(w), p->background_file);
1103 else if ((info = gtk_icon_theme_lookup_icon(p->icon_theme, "lxpanel-background", 0, 0)))
1104 {
1105 gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(w), gtk_icon_info_get_filename(info));
1106 gtk_icon_info_free(info);
1107 }
4b93d81e
HJYP
1108
1109 if (!p->background)
1110 gtk_widget_set_sensitive( w, FALSE);
3b6661f3 1111 g_object_set_data( G_OBJECT(w), "bg_image", img );
f1286efa 1112 g_signal_connect( w, "file-set", G_CALLBACK (background_changed), p);
4b93d81e
HJYP
1113 }
1114
1115 /* font color */
f1286efa 1116 w = (GtkWidget*)gtk_builder_get_object( builder, "font_clr" );
7ffaf7a5 1117 gtk_color_button_set_color( GTK_COLOR_BUTTON(w), &p->gfontcolor );
4b93d81e
HJYP
1118 g_signal_connect( w, "color-set", G_CALLBACK( on_font_color_set ), p );
1119
f1286efa 1120 w2 = (GtkWidget*)gtk_builder_get_object( builder, "use_font_clr" );
7ffaf7a5 1121 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(w2), p->usefontcolor );
3b6661f3 1122 g_object_set_data( G_OBJECT(w2), "clr", w );
4b93d81e
HJYP
1123 g_signal_connect(w2, "toggled", G_CALLBACK(on_use_font_color_toggled), p);
1124 if( ! p->usefontcolor )
1125 gtk_widget_set_sensitive( w, FALSE );
1126
1869ef90
LK
1127 /* font size */
1128 w = (GtkWidget*)gtk_builder_get_object( builder, "font_size" );
7ffaf7a5 1129 gtk_spin_button_set_value( GTK_SPIN_BUTTON(w), p->fontsize );
1869ef90
LK
1130 g_signal_connect( w, "value-changed",
1131 G_CALLBACK(on_font_size_set), p);
1132
1133 w2 = (GtkWidget*)gtk_builder_get_object( builder, "use_font_size" );
7ffaf7a5 1134 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(w2), p->usefontsize );
1869ef90
LK
1135 g_object_set_data( G_OBJECT(w2), "clr", w );
1136 g_signal_connect(w2, "toggled", G_CALLBACK(on_use_font_size_toggled), p);
1137 if( ! p->usefontsize )
1138 gtk_widget_set_sensitive( w, FALSE );
1139
4b93d81e
HJYP
1140 /* plugin list */
1141 {
f1286efa 1142 GtkWidget* plugin_list = (GtkWidget*)gtk_builder_get_object( builder, "plugin_list" );
4b93d81e
HJYP
1143
1144 /* buttons used to edit plugin list */
f1286efa 1145 w = (GtkWidget*)gtk_builder_get_object( builder, "add_btn" );
4b93d81e
HJYP
1146 g_signal_connect( w, "clicked", G_CALLBACK(on_add_plugin), plugin_list );
1147
f1286efa 1148 w = (GtkWidget*)gtk_builder_get_object( builder, "edit_btn" );
4b93d81e
HJYP
1149 g_signal_connect_swapped( w, "clicked", G_CALLBACK(modify_plugin), plugin_list );
1150 g_object_set_data( G_OBJECT(plugin_list), "edit_btn", w );
1151
f1286efa 1152 w = (GtkWidget*)gtk_builder_get_object( builder, "remove_btn" );
4b93d81e 1153 g_signal_connect( w, "clicked", G_CALLBACK(on_remove_plugin), plugin_list );
f1286efa 1154 w = (GtkWidget*)gtk_builder_get_object( builder, "moveup_btn" );
4b93d81e 1155 g_signal_connect( w, "clicked", G_CALLBACK(on_moveup_plugin), plugin_list );
f1286efa 1156 w = (GtkWidget*)gtk_builder_get_object( builder, "movedown_btn" );
4b93d81e
HJYP
1157 g_signal_connect( w, "clicked", G_CALLBACK(on_movedown_plugin), plugin_list );
1158
f1286efa 1159 w = (GtkWidget*)gtk_builder_get_object( builder, "plugin_desc" );
7ffaf7a5 1160 init_plugin_list( p, GTK_TREE_VIEW(plugin_list), w );
4b93d81e
HJYP
1161 }
1162 /* advanced, applications */
8dfa5918
AG
1163 mt = fm_mime_type_from_name("inode/directory");
1164 fm = GTK_COMBO_BOX(gtk_builder_get_object(builder, "fm_combobox"));
1165 fm_app_chooser_combo_box_setup_for_mime_type(fm, mt);
1166 fm_mime_type_unref(mt);
1167 g_signal_connect(fm, "destroy", G_CALLBACK(on_app_chooser_destroy), NULL);
4b93d81e 1168
f1286efa 1169 w = (GtkWidget*)gtk_builder_get_object( builder, "term" );
aba5758a
AG
1170 if (fm_config->terminal)
1171 gtk_entry_set_text( GTK_ENTRY(w), fm_config->terminal );
7b925596 1172 g_signal_connect( w, "focus-out-event",
de569c86 1173 G_CALLBACK(on_entry_focus_out),
aba5758a 1174 &fm_config->terminal);
4b93d81e
HJYP
1175
1176 /* If we are under LXSession, setting logout command is not necessary. */
f1286efa 1177 w = (GtkWidget*)gtk_builder_get_object( builder, "logout" );
4b93d81e
HJYP
1178 if( getenv("_LXSESSION_PID") ) {
1179 gtk_widget_hide( w );
f1286efa 1180 w = (GtkWidget*)gtk_builder_get_object( builder, "logout_label" );
4b93d81e
HJYP
1181 gtk_widget_hide( w );
1182 }
1183 else {
1184 if(logout_cmd)
7ffaf7a5 1185 gtk_entry_set_text( GTK_ENTRY(w), logout_cmd );
7b925596 1186 g_signal_connect( w, "focus-out-event",
de569c86 1187 G_CALLBACK(on_entry_focus_out_old),
4b93d81e
HJYP
1188 &logout_cmd);
1189 }
1190
82ca42af
HG
1191 w = (GtkWidget*)gtk_builder_get_object( builder, "log_level" );
1192 update_opt_menu(w, configured_log_level);
1193 g_signal_connect(w, "changed", G_CALLBACK(set_log_level), p);
1194
1195
9dd114c4 1196 panel_adjust_geometry_terminology(p);
176fb687 1197 gtk_widget_show(GTK_WIDGET(p->pref_dialog));
f1286efa 1198 w = (GtkWidget*)gtk_builder_get_object( builder, "notebook" );
7ffaf7a5 1199 gtk_notebook_set_current_page( GTK_NOTEBOOK(w), sel_page );
f1286efa
HJYP
1200
1201 g_object_unref(builder);
a52c2257
HJYP
1202}
1203
cf701cb7 1204void panel_config_save( Panel* p )
368409ba 1205{
1f4bc3aa 1206 gchar *fname;
4b93d81e 1207
1f4bc3aa
AG
1208 fname = _user_config_file_name("panels", p->name);
1209 /* existance of 'panels' dir ensured in main() */
24053345 1210
17fab6e5 1211 if (!config_write_file(p->config, fname)) {
368409ba 1212 ERR("can't open for write %s:", fname);
4b93d81e 1213 g_free( fname );
368409ba
FC
1214 RET();
1215 }
24053345 1216 g_free( fname );
cf701cb7
HJYP
1217
1218 /* save the global config file */
1219 save_global_config();
930af9fd 1220 p->config_changed = 0;
368409ba
FC
1221}
1222
389975e0 1223void restart(void)
a52c2257 1224{
f7cb330e
HJYP
1225 /* This is defined in panel.c */
1226 extern gboolean is_restarting;
a52c2257 1227 ENTER;
f7cb330e 1228 is_restarting = TRUE;
be933927 1229
f7cb330e 1230 gtk_main_quit();
a52c2257
HJYP
1231 RET();
1232}
1233
389975e0
HJYP
1234void logout(void)
1235{
88d364eb 1236 const char* l_logout_cmd = logout_cmd;
00555dcf 1237 /* If LXSession is running, _LXSESSION_PID will be set */
88d364eb
HJYP
1238 if( ! l_logout_cmd && getenv("_LXSESSION_PID") )
1239 l_logout_cmd = "lxsession-logout";
00555dcf 1240
b8d0aacd 1241 if( l_logout_cmd )
908d9fdc 1242 fm_launch_command_simple(NULL, NULL, 0, l_logout_cmd, NULL);
b8d0aacd 1243 else
3d6ee560 1244 fm_show_error(NULL, NULL, _("Logout command is not set"));
389975e0
HJYP
1245}
1246
04883e73
HJYP
1247static void notify_apply_config( GtkWidget* widget )
1248{
1249 GSourceFunc apply_func;
1250 GtkWidget* dlg;
1251
1252 dlg = gtk_widget_get_toplevel( widget );
5a343ad5 1253 apply_func = g_object_get_data( G_OBJECT(dlg), "apply_func" );
04883e73 1254 if( apply_func )
4ab8027b 1255 (*apply_func)( g_object_get_data(G_OBJECT(dlg), "apply_func_data") );
04883e73
HJYP
1256}
1257
de569c86 1258static gboolean _on_entry_focus_out_do_work(GtkWidget* edit, gpointer user_data)
04883e73
HJYP
1259{
1260 char** val = (char**)user_data;
f7cb330e 1261 const char *new_val;
7ffaf7a5 1262 new_val = gtk_entry_get_text(GTK_ENTRY(edit));
de569c86
HG
1263 if (g_strcmp0(*val, new_val) == 0) /* not changed */
1264 return FALSE;
1265 g_free( *val );
f7cb330e 1266 *val = (new_val && *new_val) ? g_strdup( new_val ) : NULL;
de569c86
HG
1267 return TRUE;
1268}
1269
1270static gboolean on_entry_focus_out_old( GtkWidget* edit, GdkEventFocus *evt, gpointer user_data )
1271{
1272 if (_on_entry_focus_out_do_work(edit, user_data))
1273 notify_apply_config( edit );
65a36853 1274 return FALSE;
04883e73
HJYP
1275}
1276
aba5758a 1277/* the same but affects fm_config instead of panel config */
de569c86 1278static gboolean on_entry_focus_out( GtkWidget* edit, GdkEventFocus *evt, gpointer user_data )
aba5758a 1279{
de569c86
HG
1280 if (_on_entry_focus_out_do_work(edit, user_data))
1281 fm_config_save(fm_config, NULL);
aba5758a
AG
1282 return FALSE;
1283}
1284
04883e73
HJYP
1285static void on_spin_changed( GtkSpinButton* spin, gpointer user_data )
1286{
1287 int* val = (int*)user_data;
1288 *val = (int)gtk_spin_button_get_value( spin );
5a343ad5 1289 notify_apply_config( GTK_WIDGET(spin) );
04883e73
HJYP
1290}
1291
1292static void on_toggle_changed( GtkToggleButton* btn, gpointer user_data )
1293{
1294 gboolean* val = (gboolean*)user_data;
1295 *val = gtk_toggle_button_get_active( btn );
5a343ad5 1296 notify_apply_config( GTK_WIDGET(btn) );
04883e73
HJYP
1297}
1298
e2957bd2
HJYP
1299static void on_file_chooser_btn_file_set(GtkFileChooser* btn, char** val)
1300{
1301 g_free( *val );
1302 *val = gtk_file_chooser_get_filename(btn);
1303 notify_apply_config( GTK_WIDGET(btn) );
1304}
1305
1306static void on_browse_btn_clicked(GtkButton* btn, GtkEntry* entry)
1307{
1308 char* file;
9dd114c4 1309 GtkFileChooserAction action = (GtkFileChooserAction) g_object_get_data(G_OBJECT(btn), "chooser-action");
65a36853 1310 GtkWidget* dlg = GTK_WIDGET(g_object_get_data(G_OBJECT(btn), "dlg"));
9dd114c4 1311 GtkWidget* fc = gtk_file_chooser_dialog_new(
1312 (action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER) ? _("Select a directory") : _("Select a file"),
65a36853 1313 GTK_WINDOW(dlg),
9dd114c4 1314 action,
e2957bd2
HJYP
1315 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
1316 GTK_STOCK_OK, GTK_RESPONSE_OK,
1317 NULL);
3b6661f3 1318 gtk_dialog_set_alternative_button_order(GTK_DIALOG(fc), GTK_RESPONSE_OK, GTK_RESPONSE_CANCEL, -1);
e2957bd2
HJYP
1319 file = (char*)gtk_entry_get_text(entry);
1320 if( file && *file )
3b6661f3
YCLP
1321 gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(fc), file );
1322 if( gtk_dialog_run(GTK_DIALOG(fc)) == GTK_RESPONSE_OK )
e2957bd2 1323 {
3b6661f3 1324 file = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fc));
e2957bd2 1325 gtk_entry_set_text(entry, file);
de569c86 1326 on_entry_focus_out_old(GTK_WIDGET(entry), NULL, g_object_get_data(G_OBJECT(dlg), "file-val"));
e2957bd2
HJYP
1327 g_free(file);
1328 }
1329 gtk_widget_destroy(fc);
1330}
1331
4ab8027b
AG
1332/* if the plugin was destroyed then destroy the dialog opened for it */
1333static void on_plugin_destroy(GtkWidget *plugin, GtkDialog *dlg)
ca443a48 1334{
4ab8027b 1335 gtk_dialog_response(dlg, GTK_RESPONSE_CLOSE);
ca443a48
FC
1336}
1337
2918994e 1338/* Handler for "response" signal from standard configuration dialog. */
4ab8027b
AG
1339static void generic_config_dlg_response(GtkWidget * dlg, int response, Panel * panel)
1340{
131514c9 1341 gpointer plugin = g_object_get_data(G_OBJECT(dlg), "generic-config-plugin");
4ab8027b
AG
1342 if (plugin)
1343 g_signal_handlers_disconnect_by_func(plugin, on_plugin_destroy, dlg);
131514c9 1344 g_object_set_data(G_OBJECT(dlg), "generic-config-plugin", NULL);
4ab8027b
AG
1345 panel->plugin_pref_dialog = NULL;
1346 gtk_widget_destroy(dlg);
1347 panel_config_save(panel);
2918994e 1348}
1349
131514c9
AG
1350void _panel_show_config_dialog(Panel *panel, GtkWidget *p, GtkWidget *dlg)
1351{
1352 /* If there is already a plugin configuration dialog open, close it.
1353 * Then record this one in case the panel or plugin is deleted. */
1354 if (panel->plugin_pref_dialog != NULL)
1355 gtk_dialog_response(GTK_DIALOG(panel->plugin_pref_dialog), GTK_RESPONSE_CLOSE);
1356 panel->plugin_pref_dialog = dlg;
1357
1358 /* add some handlers to destroy the dialog on responce or widget destroy */
1359 g_signal_connect(dlg, "response", G_CALLBACK(generic_config_dlg_response), panel);
1360 g_signal_connect(p, "destroy", G_CALLBACK(on_plugin_destroy), dlg);
1361 g_object_set_data(G_OBJECT(dlg), "generic-config-plugin", p);
1362
1363 gtk_window_present(GTK_WINDOW(dlg));
1364}
1365
bb6d6422 1366/* Parameters: const char* name, gpointer ret_value, GType type, ....NULL */
4ab8027b
AG
1367static GtkWidget *_lxpanel_generic_config_dlg(const char *title, Panel *p,
1368 GSourceFunc apply_func,
131514c9 1369 gpointer plugin,
4ab8027b 1370 const char *name, va_list args)
bb6d6422 1371{
e2957bd2 1372 GtkWidget* dlg = gtk_dialog_new_with_buttons( title, NULL, 0,
04883e73
HJYP
1373 GTK_STOCK_CLOSE,
1374 GTK_RESPONSE_CLOSE,
1375 NULL );
e7a42ecf 1376 panel_apply_icon(GTK_WINDOW(dlg));
04883e73 1377
04883e73 1378 if( apply_func )
5a343ad5 1379 g_object_set_data( G_OBJECT(dlg), "apply_func", apply_func );
4ab8027b 1380 g_object_set_data( G_OBJECT(dlg), "apply_func_data", plugin );
04883e73 1381
5a343ad5 1382 gtk_box_set_spacing( GTK_BOX(GTK_DIALOG(dlg)->vbox), 4 );
04883e73 1383
bb6d6422
HJYP
1384 while( name )
1385 {
1386 GtkWidget* label = gtk_label_new( name );
1387 GtkWidget* entry = NULL;
1388 gpointer val = va_arg( args, gpointer );
d79161b7 1389 PluginConfType type = va_arg( args, PluginConfType );
bb6d6422
HJYP
1390 switch( type )
1391 {
e2957bd2
HJYP
1392 case CONF_TYPE_STR:
1393 case CONF_TYPE_FILE_ENTRY: /* entry with a button to browse for files. */
9dd114c4 1394 case CONF_TYPE_DIRECTORY_ENTRY: /* entry with a button to browse for directories. */
bb6d6422 1395 entry = gtk_entry_new();
7414a73f
HJYP
1396 if( *(char**)val )
1397 gtk_entry_set_text( GTK_ENTRY(entry), *(char**)val );
e7a42ecf 1398 gtk_entry_set_width_chars(GTK_ENTRY(entry), 40);
7b925596 1399 g_signal_connect( entry, "focus-out-event",
de569c86 1400 G_CALLBACK(on_entry_focus_out_old), val );
bb6d6422 1401 break;
e2957bd2 1402 case CONF_TYPE_INT:
bb6d6422
HJYP
1403 {
1404 /* FIXME: the range shouldn't be hardcoded */
1405 entry = gtk_spin_button_new_with_range( 0, 1000, 1 );
5a343ad5 1406 gtk_spin_button_set_value( GTK_SPIN_BUTTON(entry), *(int*)val );
16fb8c2e 1407 g_signal_connect( entry, "value-changed",
92d76f06 1408 G_CALLBACK(on_spin_changed), val );
bb6d6422
HJYP
1409 break;
1410 }
e2957bd2 1411 case CONF_TYPE_BOOL:
bb6d6422 1412 entry = gtk_check_button_new();
5a343ad5
JH
1413 gtk_container_add( GTK_CONTAINER(entry), label );
1414 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(entry), *(gboolean*)val );
16fb8c2e 1415 g_signal_connect( entry, "toggled",
92d76f06 1416 G_CALLBACK(on_toggle_changed), val );
bb6d6422 1417 break;
e2957bd2
HJYP
1418 case CONF_TYPE_FILE:
1419 entry = gtk_file_chooser_button_new(_("Select a file"), GTK_FILE_CHOOSER_ACTION_OPEN);
1420 if( *(char**)val )
1421 gtk_file_chooser_set_filename( GTK_FILE_CHOOSER(entry), *(char**)val );
1422 g_signal_connect( entry, "file-set",
1423 G_CALLBACK(on_file_chooser_btn_file_set), val );
e7a42ecf 1424 break;
1425 case CONF_TYPE_TRIM:
1426 {
1427 entry = gtk_label_new(NULL);
1428 char *markup = g_markup_printf_escaped ("<span style=\"italic\">%s</span>", name );
1429 gtk_label_set_markup (GTK_LABEL (entry), markup);
1430 g_free (markup);
1431 }
1432 break;
bb6d6422
HJYP
1433 }
1434 if( entry )
1435 {
e7a42ecf 1436 if(( type == CONF_TYPE_BOOL ) || ( type == CONF_TYPE_TRIM ))
5a343ad5 1437 gtk_box_pack_start( GTK_BOX(GTK_DIALOG(dlg)->vbox), entry, FALSE, FALSE, 2 );
bb6d6422
HJYP
1438 else
1439 {
1440 GtkWidget* hbox = gtk_hbox_new( FALSE, 2 );
5a343ad5
JH
1441 gtk_box_pack_start( GTK_BOX(hbox), label, FALSE, FALSE, 2 );
1442 gtk_box_pack_start( GTK_BOX(hbox), entry, TRUE, TRUE, 2 );
1443 gtk_box_pack_start( GTK_BOX(GTK_DIALOG(dlg)->vbox), hbox, FALSE, FALSE, 2 );
9dd114c4 1444 if ((type == CONF_TYPE_FILE_ENTRY) || (type == CONF_TYPE_DIRECTORY_ENTRY))
e2957bd2
HJYP
1445 {
1446 GtkWidget* browse = gtk_button_new_with_mnemonic(_("_Browse"));
1447 gtk_box_pack_start( GTK_BOX(hbox), browse, TRUE, TRUE, 2 );
65a36853 1448 g_object_set_data(G_OBJECT(dlg), "file-val", val);
3b6661f3 1449 g_object_set_data(G_OBJECT(browse), "dlg", dlg);
cb29d20d 1450
fcb35553
PS
1451 GtkFileChooserAction action = GTK_FILE_CHOOSER_ACTION_OPEN;
1452 if (type == CONF_TYPE_DIRECTORY_ENTRY)
1453 {
1454 action = GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER;
1455 }
1456
c95393d3 1457 g_object_set_data(G_OBJECT(browse), "chooser-action", GINT_TO_POINTER(action));
e2957bd2
HJYP
1458 g_signal_connect( browse, "clicked", G_CALLBACK(on_browse_btn_clicked), entry );
1459 }
bb6d6422
HJYP
1460 }
1461 }
1462 name = va_arg( args, const char* );
1463 }
04a2f050 1464
04a2f050
HJYP
1465 gtk_container_set_border_width( GTK_CONTAINER(dlg), 8 );
1466
04883e73 1467 gtk_widget_show_all( dlg );
131514c9 1468
04883e73 1469 return dlg;
bb6d6422
HJYP
1470}
1471
4ab8027b
AG
1472/* new plugins API -- apply_func() gets GtkWidget* */
1473GtkWidget *lxpanel_generic_config_dlg(const char *title, Panel *panel,
1474 GSourceFunc apply_func, GtkWidget *plugin,
1475 const char *name, ...)
1476{
1477 GtkWidget *dlg;
1478 va_list args;
1479
1480 if (plugin == NULL)
1481 return NULL;
1482 va_start(args, name);
131514c9 1483 dlg = _lxpanel_generic_config_dlg(title, panel, apply_func, plugin, name, args);
4ab8027b
AG
1484 va_end(args);
1485 return dlg;
1486}
1487
1488/* for old plugins compatibility -- apply_func() gets Plugin* */
1489GtkWidget* create_generic_config_dlg( const char* title, GtkWidget* parent,
1490 GSourceFunc apply_func, Plugin * plugin,
1491 const char* name, ... )
1492{
1493 GtkWidget *dlg;
1494 va_list args;
1495
1496 if (plugin == NULL)
1497 return NULL;
1498 va_start(args, name);
131514c9 1499 dlg = _lxpanel_generic_config_dlg(title, plugin->panel, apply_func, plugin, name, args);
4ab8027b 1500 va_end(args);
131514c9 1501 _panel_show_config_dialog(plugin->panel, plugin->pwid, dlg);
4ab8027b
AG
1502 return dlg;
1503}
1504
cf701cb7
HJYP
1505const char command_group[] = "Command";
1506void load_global_config()
1507{
1508 GKeyFile* kf = g_key_file_new();
1f4bc3aa
AG
1509 char* file = _old_system_config_file_name("config");
1510 gboolean loaded = FALSE;
1511
1512 /* try to load system config file first */
1513 if (g_key_file_load_from_file(kf, file, 0, NULL))
1514 loaded = TRUE;
1515 else /* fallback to old config place for backward compatibility */
cf701cb7 1516 {
1f4bc3aa
AG
1517 g_free(file);
1518 file = _system_config_file_name("config");
1519 if (g_key_file_load_from_file(kf, file, 0, NULL))
1520 loaded = TRUE;
cf701cb7 1521 }
1f4bc3aa
AG
1522 /* now try to load user config file */
1523 g_free(file);
1524 file = _user_config_file_name("config", NULL);
1525 if (g_key_file_load_from_file(kf, file, 0, NULL))
1526 loaded = TRUE;
1527 g_free(file);
cf701cb7
HJYP
1528
1529 if( loaded )
1530 {
cb29d20d
AG
1531 char *fm, *tmp;
1532 GList *apps, *l;
1533
cf701cb7 1534 logout_cmd = g_key_file_get_string( kf, command_group, "Logout", NULL );
cb29d20d
AG
1535 /* check for terminal setting on upgrade */
1536 if (fm_config->terminal == NULL)
1537 fm_config->terminal = g_key_file_get_string(kf, command_group,
1538 "Terminal", NULL);
1539 /* this is heavy but fortunately it will be ran only once: on upgrade */
1540 fm = g_key_file_get_string(kf, command_group, "FileManager", NULL);
1541 if (fm)
1542 {
1543 tmp = strchr(fm, ' '); /* chop params */
1544 if (tmp)
1545 *tmp = '\0';
1546 tmp = strrchr(fm, '/'); /* use only basename */
1547 if (tmp)
1548 tmp++;
1549 else
1550 tmp = fm;
1551 tmp = g_strdup_printf("%s.desktop", tmp); /* generate desktop id */
1552 g_free(fm);
1553 apps = g_app_info_get_all_for_type("inode/directory");
1554 for (l = apps; l; l = l->next) /* scan all known applications */
1555 if (strcmp(tmp, g_app_info_get_id(l->data)) == 0)
1556 break;
1557 if (l != NULL) /* found */
1558 g_app_info_set_as_default_for_type(l->data, "inode/directory",
1559 NULL);
1560 else
1561 g_warning("the %s is not valid desktop id of file manager", tmp);
1562 for (l = apps; l; l = l->next) /* free retrieved data */
1563 g_object_unref(l->data);
1564 g_list_free(apps);
1565 g_free(tmp);
1566 }
cf701cb7
HJYP
1567 }
1568 g_key_file_free( kf );
1569}
1570
b7629dc7 1571static void save_global_config()
cf701cb7 1572{
1f4bc3aa 1573 char* file = _user_config_file_name("config", NULL);
cf701cb7
HJYP
1574 FILE* f = fopen( file, "w" );
1575 if( f )
1576 {
1577 fprintf( f, "[%s]\n", command_group );
cf701cb7
HJYP
1578 if( logout_cmd )
1579 fprintf( f, "Logout=%s\n", logout_cmd );
1580 fclose( f );
1581 }
1582}
1583
1584void free_global_config()
1585{
cf701cb7
HJYP
1586 g_free( logout_cmd );
1587}
1588
8dfa5918
AG
1589/* this is dirty and should be removed later */
1590const char*
cf701cb7
HJYP
1591lxpanel_get_file_manager()
1592{
8dfa5918
AG
1593 GAppInfo *app = g_app_info_get_default_for_type("inode/directory", TRUE);
1594 static char *exec = NULL;
1595 const char *c, *x;
1596
1597 if (!app)
1598 return "pcmanfm %s";
1599 c = g_app_info_get_commandline(app);
1600 x = strchr(c, ' '); /* skip all arguments */
1601 g_free(exec);
1602 if (x)
1603 exec = g_strndup(c, x - c);
1604 else
1605 exec = g_strdup(c);
1606 return exec;
cf701cb7
HJYP
1607}
1608
b8d0aacd 1609/* vim: set sw=4 et sts=4 : */