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