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