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