1 /* logjam - a GTK client for LiveJournal.
2 * Copyright (C) 2000-2003 Evan Martin <evan@livejournal.com>
11 #include "checkfriends.h"
13 #include "groupedbox.h"
20 #include "smartquotes.h"
26 /* what's this? all of these funny structures in the settings box?
27 * well, instead of creating and tearing down all of these widgets, i
28 * try to pull out shared functionality.
30 * it's loosely inspired by george lebl's pong http://www.5z.com/jirka/pong-documentation/
31 * but i've never actaully read how that works.
33 * we have a collection of SettingsWidgets that track their name and
34 * configuration option, and then it's all nicely automated through functions
50 typedef struct _SettingsWidget SettingsWidget
;
51 struct _SettingsWidget
{
54 SettingsWidgetType type
;
56 gpointer data
; /* extra pointer, to be used as needed. */
57 gpointer data2
; /* extra pointer for wimps. */
63 static void run_cfmask_settings_dlg (SettingsWidget
*sw
);
66 static SettingsWidget settingswidgets
[] = {
67 {"ui_revertusejournal", &conf
.options
.revertusejournal
,
68 SW_TOGGLE
, N_("_Revert to primary journal after posting on a community"), NULL
},
69 {"ui_defaultsecurity", &conf
.defaultsecurity
,
70 SW_CUSTOM
, N_("Default _security on posts:")},
71 {"ui_autosave", &conf
.options
.autosave
,
72 SW_TOGGLE
, N_("Automatically save _drafts (for crash recovery)")},
74 {"ui_allowmultipleinstances", &conf
.options
.allowmultipleinstances
,
75 SW_TOGGLE
, N_("Allow multiple _instances of LogJam to run simultaneously")},
77 {"ui_spellcheck", &conf
.options
.usespellcheck
,
78 SW_TOGGLE
, N_("_Use spell check")},
79 {"ui_spell_language", &conf
.spell_language
,
80 SW_TEXT
, N_("Entry _language:")},
82 {"ui_smartquotes", &conf
.options
.smartquotes
,
83 SW_TOGGLE
, N_("Automatically change _quotes to matching pairs")},
84 {"ui_smartquotes_ru", &conf
.options
.smartquotes_russian
,
85 SW_TOGGLE
, N_("'Russian' _typographical mode")},
86 {"ui_font", &conf
.uifont
,
87 SW_CUSTOM
, N_("Entry display font:")},
88 {"ui_docklet", &conf
.options
.docklet
,
89 SW_TOGGLE
, N_("Add icon to system _tray (for GNOME/KDE/etc. dock)")},
91 {"web_spawn", &conf
.spawn_command
,
92 SW_COMMAND
, N_("Web browser:"), (gpointer
) spawn_commands
},
94 {"music_command", &conf
.music_command
,
95 SW_COMMAND
, N_("Detect music from:"), (gpointer
) music_commands
},
97 {"net_useproxy", &conf
.options
.useproxy
,
98 SW_TOGGLE
, N_("Use _proxy server")},
99 {"net_proxy", &conf
.proxy
,
100 SW_TEXT
, N_("UR_L:")},
102 {"net_useproxyauth", &conf
.options
.useproxyauth
,
103 SW_TOGGLE
, N_("Use proxy _authentication")},
104 {"net_proxyuser", &conf
.proxyuser
,
105 SW_TEXT
, N_("_User:")},
106 {"net_proxypass", &conf
.proxypass
,
107 SW_TEXT
, N_("_Password:")},
109 {"debug_netdump", &conf
.options
.netdump
,
110 SW_TOGGLE
, N_("Dump _network data on stderr")},
111 {"debug_nofork", &conf
.options
.nofork
,
112 SW_TOGGLE
, N_("Don't _fork on network requests")},
115 {"cf_autostart", &conf
.options
.cfautostart
,
116 SW_TOGGLE
, N_("_Monitor friends list for new entries upon login")},
117 {"cf_usemask", &conf
.options
.cfusemask
,
118 SW_TOGGLE
, N_("_Limit monitoring to groups of friends")},
119 {"cf_mask", NULL
/* set at runtime to that of current user */ ,
121 {"cf_userinterval", &conf
.cfuserinterval
,
122 SW_SPIN_INTEGER
, N_("_Check friends list every " /* X seconds */ )},
123 {"cf_threshold", &conf
.cfthreshold
,
124 SW_SPIN_INTEGER
, N_("_Notify me after " /* X new entires */ )},
125 {"cf_float", &conf
.options
.cffloat
,
126 SW_TOGGLE
, N_("_Floating indicator")},
127 {"cf_floatraise", &conf
.options
.cffloatraise
,
128 SW_TOGGLE
, N_("_Raise floating indicator when new entries detected")},
129 {"cf_float_decorate", &conf
.options
.cffloat_decorate
,
130 SW_TOGGLE
, N_("Show _titlebar on floating indicator")},
136 static SettingsWidget
*sw_lookup (const char *name
) {
137 for (SettingsWidget
*sw
= settingswidgets
; sw
->name
; ++sw
) if (strcmp(name
, sw
->name
) == 0) return sw
;
138 g_error("sw_lookup failed for %s", name
);
143 static void toggle_enable_cb (GtkWidget
*toggle
, GtkWidget
*target
) {
144 gtk_widget_set_sensitive(target
, gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toggle
)));
148 static void toggle_tie_enable (GtkWidget
*toggle
, GtkWidget
*target
) {
149 gtk_widget_set_sensitive(target
, gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toggle
)));
150 g_signal_connect(G_OBJECT(toggle
), "toggled", G_CALLBACK(toggle_enable_cb
), target
);
154 static void toggle_tie (SettingsWidget
*sw
) {
155 tie_toggle(GTK_TOGGLE_BUTTON(sw
->widget
), (gboolean
*)sw
->conf
);
159 static void radio_tie_cb (GtkToggleButton
*toggle
, SettingsWidget
*sw
) {
160 if (gtk_toggle_button_get_active(toggle
)) *(int *)sw
->conf
= GPOINTER_TO_INT(sw
->data
);
164 static void radio_tie(SettingsWidget
*sw
) {
165 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(sw
->widget
), *(gint
*)sw
->conf
== GPOINTER_TO_INT(sw
->data
));
166 g_signal_connect(G_OBJECT(sw
->widget
), "toggled", G_CALLBACK(radio_tie_cb
), sw
);
170 static void text_tie (SettingsWidget
*sw
) {
171 tie_text(GTK_ENTRY(sw
->widget
), (char **)sw
->conf
);
175 static void integer_tie_cb (GtkEditable
*e
, SettingsWidget
*sw
) {
176 char *text
= gtk_editable_get_chars(e
, 0, -1);
177 *(int *)sw
->conf
= atoi(text
);
182 static void integer_tie (SettingsWidget
*sw
) {
184 snprintf(buf
, sizeof(buf
), "%d", *(int *)sw
->conf
);
185 gtk_entry_set_text(GTK_ENTRY(sw
->widget
), buf
);
186 g_signal_connect(G_OBJECT(sw
->widget
), "changed", G_CALLBACK(integer_tie_cb
), sw
);
190 static void spin_integer_tie_cb (GtkSpinButton
*b
, SettingsWidget
*sw
) {
191 *(gint
*)sw
->conf
= (gint
) gtk_spin_button_get_value(b
);
195 static void spin_integer_tie (SettingsWidget
*sw
) {
196 g_signal_connect(G_OBJECT(sw
->widget
), "value-changed", G_CALLBACK(spin_integer_tie_cb
), sw
);
200 static void combo_tie(SettingsWidget
*sw
) {
201 tie_combo(GTK_COMBO(sw
->widget
), (char **)sw
->conf
);
205 static void command_changed_cb (GtkOptionMenu
*omenu
, SettingsWidget
*sw
) {
206 CommandList
*cmds
= sw
->data
;
207 int cur
= gtk_option_menu_get_history(GTK_OPTION_MENU(sw
->widget
));
208 jam_widget_set_visible(sw
->data2
, cmds
[cur
].label
== NULL
);
209 if (cmds
[cur
].label
!= NULL
) {
210 const char *cmd
= cmds
[cur
].command
;
211 string_replace((char **)sw
->conf
, (cmd
? g_strdup(cmd
) : NULL
));
212 gtk_entry_set_text(GTK_ENTRY(sw
->subwidget
), (cmd
? cmd
: ""));
217 static GtkWidget
*command_make (SettingsWidget
*sw
) {
218 CommandList
*cmds
= sw
->data
;
219 GtkWidget
*vbox
, *menu
;
221 char *cmd
= *((char **)sw
->conf
);
225 menu
= gtk_menu_new();
226 for (i
= 0; cmds
[i
].label
; ++i
) {
227 const char *curcmd
= cmds
[i
].command
;
228 gtk_menu_shell_append(GTK_MENU_SHELL(menu
), gtk_menu_item_new_with_label(_(cmds
[i
].label
)));
229 if (cur
== -1 && ((cmd
== curcmd
) || (cmd
&& curcmd
&& (strcmp(cmd
, curcmd
) == 0))))
232 gtk_menu_shell_append(GTK_MENU_SHELL(menu
), gtk_menu_item_new_with_label(_("Custom Command")));
233 if (cur
== -1) cur
= i
;
235 sw
->widget
= gtk_option_menu_new();
236 gtk_option_menu_set_menu(GTK_OPTION_MENU(sw
->widget
), menu
);
237 gtk_option_menu_set_history(GTK_OPTION_MENU(sw
->widget
), cur
);
239 sw
->subwidget
= gtk_entry_new();
240 tie_text(GTK_ENTRY(sw
->subwidget
), (char **)sw
->conf
);
242 g_signal_connect(G_OBJECT(sw
->widget
), "changed", G_CALLBACK(command_changed_cb
), sw
);
243 jam_widget_set_visible(sw
->subwidget
, cur
== i
);
245 sg
= gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL
);
246 vbox
= gtk_vbox_new(FALSE
, 3);
247 gtk_box_pack_start(GTK_BOX(vbox
), labelled_box_new_sg(_(sw
->caption
), sw
->widget
, sg
), FALSE
, FALSE
, 0);
248 sw
->data2
= labelled_box_new_sg(NULL
, sw
->subwidget
, sg
); /* ugh. */
249 gtk_box_pack_start(GTK_BOX(vbox
), sw
->data2
, FALSE
, FALSE
, 0);
254 static GtkWidget
*sw_make_sg (const char *name
, GtkSizeGroup
*sg
) {
255 SettingsWidget
*sw
= sw_lookup(name
);
258 sw
->widget
= gtk_check_button_new_with_mnemonic(_(sw
->caption
));
262 sw
->widget
= gtk_radio_button_new_with_mnemonic(NULL
, _(sw
->caption
));
266 sw
->widget
= gtk_entry_new();
268 return labelled_box_new_sg(_(sw
->caption
), sw
->widget
, sg
);
270 sw
->widget
= gtk_entry_new();
271 gtk_entry_set_width_chars(GTK_ENTRY(sw
->widget
), 4);
273 return labelled_box_new(_(sw
->caption
), sw
->widget
);
274 case SW_SPIN_INTEGER
:
276 gdouble default_value
= *(gint
*) sw
->conf
;
277 GtkObject
*adj
= gtk_adjustment_new(default_value
,
278 /* client code should override these */
279 G_MINDOUBLE
, G_MAXDOUBLE
, 1.0, 1.0, 1.0);
280 sw
->widget
= gtk_spin_button_new(GTK_ADJUSTMENT(adj
), 1, 1);
282 spin_integer_tie(sw
);
283 return labelled_box_new_expand(_(sw
->caption
), sw
->widget
, FALSE
);
285 sw
->widget
= gtk_combo_new();
287 return labelled_box_new(_(sw
->caption
), sw
->widget
);
289 return command_make(sw
);
291 if (sw
->caption
&& sw
->widget
) return labelled_box_new(_(sw
->caption
), sw
->widget
);
300 static GtkWidget
*sw_make (const char *name
) {
301 return sw_make_sg(name
, NULL
);
305 static void sec_changed_cb (SecMgr
*sm
, SettingsWidget
*sw
) {
306 secmgr_security_get(sm
, (LJSecurity
*)sw
->conf
);
310 static void run_fontsel_settings_dlg (SettingsWidget
*sw
) {
312 const gchar
*newfont
;
315 dlg
= gtk_font_selection_dialog_new(_("Select font"));
316 gtk_font_selection_dialog_set_font_name(GTK_FONT_SELECTION_DIALOG(dlg
), gtk_label_get_text(GTK_LABEL(sw
->widget
)));
318 if (gtk_dialog_run(GTK_DIALOG(dlg
)) == GTK_RESPONSE_OK
) {
319 gtk_label_set_text(GTK_LABEL(sw
->widget
), gtk_font_selection_dialog_get_font_name(GTK_FONT_SELECTION_DIALOG(dlg
)));
322 newfont
= gtk_label_get_text(GTK_LABEL(sw
->widget
));
323 oldfont
= pango_font_description_to_string(pango_context_get_font_description(gtk_widget_get_pango_context(GTK_WIDGET(sw
->data
))));
325 if (newfont
&& g_ascii_strcasecmp(oldfont
, newfont
) != 0) {
326 string_replace(sw
->conf
, g_strdup(newfont
));
327 jam_widget_set_font(sw
->widget
, newfont
);
328 jam_widget_set_font(sw
->data
, newfont
);
332 gtk_widget_destroy(dlg
);
337 extern void docklet_enable (GtkWidget
*win
, gboolean enable
);
339 static void docklet_change_cb (GtkToggleButton
*tb
, JamWin
*jw
) {
340 docklet_enable(GTK_WIDGET(jw
), gtk_toggle_button_get_active(tb
));
342 #endif /* USE_DOCK */
345 static GtkWidget
*uisettings (JamWin
*jw
) {
347 GtkWidget
*vbox
, *hbox
, *button
;
348 char *fontname
= NULL
;
349 GtkWidget
*post
, *entry
, *misc
;
351 vbox
= gtk_vbox_new(FALSE
, 18);
352 gtk_container_set_border_width(GTK_CONTAINER(vbox
), 10);
354 post
= groupedbox_new_with_text(_("Posting"));
355 gtk_box_pack_start(GTK_BOX(vbox
), post
, FALSE
, FALSE
, 0);
357 groupedbox_pack(GROUPEDBOX(post
), sw_make("ui_revertusejournal"), FALSE
);
359 sw
= sw_lookup("ui_defaultsecurity");
360 sw
->widget
= secmgr_new(FALSE
);
361 secmgr_security_set(SECMGR(sw
->widget
), (LJSecurity
*) sw
->conf
);
362 g_signal_connect(G_OBJECT(sw
->widget
), "changed", G_CALLBACK(sec_changed_cb
), sw
);
363 groupedbox_pack(GROUPEDBOX(post
), sw_make("ui_defaultsecurity"), FALSE
);
365 entry
= groupedbox_new_with_text(_("Entries"));
366 gtk_box_pack_start(GTK_BOX(vbox
), entry
, FALSE
, FALSE
, 0);
368 groupedbox_pack(GROUPEDBOX(entry
), sw_make("ui_autosave"), FALSE
);
372 GtkWidget
*toggle
= sw_make("ui_spellcheck");
373 GtkWidget
*label
, *box
;
375 hbox
= sw_make("ui_spell_language");
376 label
= gtk_label_new(" ");
377 gtk_box_pack_start(GTK_BOX(hbox
), label
, FALSE
, FALSE
, 0);
378 gtk_box_reorder_child(GTK_BOX(hbox
), label
, 0);
380 sw
= sw_lookup("ui_spell_language");
381 gtk_entry_set_width_chars(GTK_ENTRY(sw
->widget
), 5);
383 box
= gtk_vbox_new(FALSE
, 3);
384 gtk_box_pack_start(GTK_BOX(box
), toggle
, FALSE
, FALSE
, 0);
385 gtk_box_pack_start(GTK_BOX(box
), hbox
, FALSE
, FALSE
, 0);
387 groupedbox_pack(GROUPEDBOX(entry
), box
, FALSE
);
388 toggle_tie_enable(toggle
, hbox
);
392 groupedbox_pack(GROUPEDBOX(entry
), sw_make("ui_smartquotes"), FALSE
);
393 groupedbox_pack(GROUPEDBOX(entry
), sw_make("ui_smartquotes_ru"), FALSE
);
395 sw
= sw_lookup("ui_font");
396 if (conf
.uifont
== NULL
) {
397 fontname
= pango_font_description_to_string(pango_context_get_font_description(gtk_widget_get_pango_context(jw
->view
)));
398 sw
->widget
= gtk_label_new(fontname
? fontname
: _("[gtk default]"));
399 if (fontname
) jam_widget_set_font(sw
->widget
, fontname
);
402 sw
->widget
= gtk_label_new(conf
.uifont
);
403 jam_widget_set_font(sw
->widget
, conf
.uifont
);
405 button
= gtk_button_new_from_stock(GTK_STOCK_SELECT_FONT
);
408 hbox
= labelled_box_new_expand(_(sw
->caption
), button
, FALSE
);
409 gtk_box_pack_start(GTK_BOX(hbox
), sw
->widget
, TRUE
, TRUE
, 0);
410 gtk_box_reorder_child(GTK_BOX(hbox
), sw
->widget
, 1);
412 groupedbox_pack(GROUPEDBOX(entry
), hbox
, FALSE
);
413 g_signal_connect_swapped(G_OBJECT(button
), "clicked", G_CALLBACK(run_fontsel_settings_dlg
), sw
);
415 misc
= groupedbox_new_with_text(_("Behavior"));
416 gtk_box_pack_start(GTK_BOX(vbox
), misc
, FALSE
, FALSE
, 0);
418 groupedbox_pack(GROUPEDBOX(misc
), sw_make("ui_allowmultipleinstances"), FALSE
);
421 button
= sw_make("ui_docklet");
422 g_signal_connect(G_OBJECT(button
), "toggled", G_CALLBACK(docklet_change_cb
), jw
);
423 groupedbox_pack(GROUPEDBOX(misc
), button
, FALSE
);
424 #endif /* USE_DOCK */
430 static GtkWidget
*proxyuserpass (void) {
431 GtkWidget
*vbox
= gtk_vbox_new(FALSE
, 6);
432 GtkSizeGroup
*sg
= gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL
);
433 gtk_box_pack_start(GTK_BOX(vbox
), sw_make_sg("net_proxyuser", sg
), FALSE
, FALSE
, 0);
434 gtk_box_pack_start(GTK_BOX(vbox
), sw_make_sg("net_proxypass", sg
), FALSE
, FALSE
, 0);
439 static void music_diagnose (GtkWidget
*button
) {
440 GtkWindow
*dlg
= GTK_WINDOW(gtk_widget_get_toplevel(button
));
442 char *music
, *result
;
443 MusicSource source
= music_current_source();
445 if (!music_can_detect(&err
)) {
446 jam_warning(dlg
, "%s", err
->message
);
451 music
= music_detect(&err
);
453 if (source
== MUSIC_SOURCE_XMMS
&& err
->domain
== G_SPAWN_ERROR
&& err
->code
== G_SPAWN_ERROR_NOENT
) {
454 jam_warning(dlg
, _("LogJam XMMS helper not found. " "Did you install LogJam's XMMS support?"));
456 jam_warning(dlg
, _("Error detecting music: %s"), err
->message
);
461 result
= g_strdup_printf(_("Music detection succeeded.\n\nCurrent music:\n%s"), music
);
462 jam_messagebox(dlg
, _("Music Detection"), result
);
468 static GtkWidget
*proxysettings (void) {
469 GtkWidget
*group
, *wbox
, *hbox
, *cb
, *table
, *authgroup
;
471 group
= groupedbox_new_with_text(_("Proxy"));
473 cb
= sw_make("net_useproxy");
474 groupedbox_pack(GROUPEDBOX(group
), cb
, FALSE
);
476 wbox
= gtk_vbox_new(FALSE
, 6);
477 toggle_tie_enable(cb
, wbox
);
478 groupedbox_pack(GROUPEDBOX(group
), wbox
, FALSE
);
480 hbox
= sw_make("net_proxy");
481 gtk_box_pack_start(GTK_BOX(wbox
), hbox
, FALSE
, FALSE
, 0);
483 cb
= sw_make("net_useproxyauth");
484 gtk_box_pack_start(GTK_BOX(wbox
), cb
, FALSE
, FALSE
, 0);
486 table
= proxyuserpass();
487 authgroup
= groupedbox_new();
488 groupedbox_pack(GROUPEDBOX(authgroup
), table
, FALSE
);
489 gtk_box_pack_start(GTK_BOX(wbox
), authgroup
, FALSE
, FALSE
, 0);
491 toggle_tie_enable(cb
, table
);
497 static GtkWidget
*programsettings (JamWin
*jw
) {
499 GtkWidget
*button
, *hbox
;
501 JamView
*jv
= jam_win_get_cur_view(jw
);
503 group
= groupedbox_new_with_text(_("Programs"));
504 groupedbox_pack(GROUPEDBOX(group
), sw_make("web_spawn"), FALSE
);
506 groupedbox_pack(GROUPEDBOX(group
), sw_make("music_command"), FALSE
);
507 sw
= sw_lookup("music_command");
508 g_signal_connect_swapped(G_OBJECT(sw
->widget
), "changed", G_CALLBACK(jam_view_settings_changed
), jv
);
510 button
= gtk_button_new_with_mnemonic(_("_Diagnose"));
511 g_signal_connect(G_OBJECT(button
), "clicked", G_CALLBACK(music_diagnose
), NULL
);
512 hbox
= labelled_box_new_expand(_("Diagnose problems detecting music:"), button
, FALSE
);
513 groupedbox_pack(GROUPEDBOX(group
), hbox
, FALSE
);
519 static GtkWidget
*systemsettings (JamWin
*jw
) {
522 vbox
= gtk_vbox_new(FALSE
, 18);
523 gtk_container_set_border_width(GTK_CONTAINER(vbox
), 10);
524 gtk_box_pack_start(GTK_BOX(vbox
), programsettings(jw
), FALSE
, FALSE
, 0);
525 gtk_box_pack_start(GTK_BOX(vbox
), proxysettings(), FALSE
, FALSE
, 0);
530 static GtkWidget
*debugsettings (GtkWidget
*dlg
) {
531 GtkWidget
*vbox
, *gb
;
533 vbox
= gtk_vbox_new(FALSE
, 18);
534 gtk_container_set_border_width(GTK_CONTAINER(vbox
), 10);
536 gb
= groupedbox_new_with_text(_("Network"));
537 gtk_box_pack_start(GTK_BOX(vbox
), gb
, FALSE
, FALSE
, 0);
539 groupedbox_pack(GROUPEDBOX(gb
), sw_make("debug_netdump"), FALSE
);
540 groupedbox_pack(GROUPEDBOX(gb
), sw_make("debug_nofork"), FALSE
);
546 static GtkWidget
*cfriends_general_settings (JamAccountLJ
*acc
) {
547 GtkWidget
*general
, *b
, *w
;
550 general
= groupedbox_new_with_text(_("General"));
552 groupedbox_pack(GROUPEDBOX(general
), sw_make("cf_autostart"), FALSE
);
554 b
= sw_make("cf_threshold");
555 sw
= sw_lookup("cf_threshold");
557 jam_spin_button_set(GTK_SPIN_BUTTON(w
), TRUE
/* numeric */ ,
558 1.0, 7.0 /* range */ , 1.0, 1.0 /*increments */ , 0 /* digits */ );
559 gtk_box_pack_start(GTK_BOX(b
), gtk_label_new(_("new entries by my friends")), FALSE
, FALSE
, 5);
560 /* XXX: ugly, because it defaults to "1 entries". Yuck. */
561 groupedbox_pack(GROUPEDBOX(general
), b
, FALSE
);
563 b
= sw_make("cf_userinterval");
564 sw
= sw_lookup("cf_userinterval");
566 jam_spin_button_set(GTK_SPIN_BUTTON(w
), TRUE
/*numeric */ , 45.0, 3600.0 /*range */ , 1.0, 10.0 /*increments */ , 0 /*digits */ );
567 gtk_box_pack_start(GTK_BOX(b
), gtk_label_new(_("seconds")), FALSE
, FALSE
, 5);
568 groupedbox_pack(GROUPEDBOX(general
), b
, FALSE
);
574 static GtkWidget
*cfriends_filter_settings (JamAccountLJ
*acc
) {
575 GtkWidget
*filter
, *maskhbox
, *l
;
577 LJUser
*u
= jam_account_lj_get_user(acc
);
579 filter
= groupedbox_new_with_text(_("Filter"));
581 maskhbox
= gtk_hbox_new(FALSE
, 5);
582 gtk_box_pack_start(GTK_BOX(maskhbox
), sw_make("cf_usemask"), FALSE
, FALSE
, 0);
583 sw
= sw_lookup("cf_mask");
585 sw
->widget
= gtk_button_new_with_label(_("Choose filter"));
586 gtk_box_pack_start(GTK_BOX(maskhbox
), GTK_WIDGET(sw
->widget
), FALSE
, FALSE
, 0);
587 gtk_widget_set_sensitive(sw
->widget
, u
->friendgroups
!= NULL
);
588 g_signal_connect_swapped(G_OBJECT(sw
->widget
), "clicked", G_CALLBACK(run_cfmask_settings_dlg
), sw
);
589 l
= gtk_label_new(NULL
);
590 gtk_label_set_markup(GTK_LABEL(l
), _("<small>The filter chosen here only affects the " "current user.</small>"));
591 gtk_label_set_line_wrap(GTK_LABEL(l
), TRUE
);
592 gtk_label_set_justify(GTK_LABEL(l
), GTK_JUSTIFY_LEFT
);
594 groupedbox_pack(GROUPEDBOX(filter
), maskhbox
, FALSE
);
595 groupedbox_pack(GROUPEDBOX(filter
), l
, FALSE
);
601 static void float_change_cb (GtkWidget
*w
, CFMgr
*cfm
) {
602 cf_app_update_float();
606 static GtkWidget
*cfriends_indicators_settings (CFMgr
*cfm
) {
607 GtkWidget
*indicators
, *floaters
, *b
, *w
;
610 indicators
= groupedbox_new_with_text(_("Indicators"));
612 b
= sw_make("cf_float");
613 g_signal_connect(G_OBJECT(b
), "toggled", G_CALLBACK(float_change_cb
), cfm
);
614 sw
= sw_lookup("cf_float");
616 groupedbox_pack(GROUPEDBOX(indicators
), b
, FALSE
);
618 floaters
= groupedbox_new();
619 groupedbox_pack(GROUPEDBOX(indicators
), floaters
, FALSE
);
621 groupedbox_pack(GROUPEDBOX(floaters
), sw_make("cf_floatraise"), FALSE
);
622 b
= sw_make("cf_float_decorate");
623 g_signal_connect(G_OBJECT(b
), "toggled", G_CALLBACK(cf_float_decorate_refresh
), NULL
);
624 groupedbox_pack(GROUPEDBOX(floaters
), b
, FALSE
);
626 toggle_tie_enable(w
, floaters
);
632 static GtkWidget
*cfriendssettings (CFMgr
*cfm
) {
634 JamAccountLJ
*acc
= cfmgr_get_account(cfm
);
636 vbox
= gtk_vbox_new(FALSE
, 18);
637 gtk_container_set_border_width(GTK_CONTAINER(vbox
), 10);
640 gtk_box_pack_start(GTK_BOX(vbox
), cfriends_general_settings(acc
), FALSE
, FALSE
, 0);
643 gtk_box_pack_start(GTK_BOX(vbox
), cfriends_filter_settings(acc
), FALSE
, FALSE
, 0);
646 gtk_box_pack_start(GTK_BOX(vbox
), cfriends_indicators_settings(cfm
), FALSE
, FALSE
, 0);
652 static void run_settings_dialog (JamWin
*jw
) {
655 dlg
= gtk_dialog_new_with_buttons(_("Preferences"), GTK_WINDOW(jw
), GTK_DIALOG_MODAL
, GTK_STOCK_CLOSE
, GTK_RESPONSE_CLOSE
, NULL
);
657 /* the order of notebook pages created here should match the
658 * SettingsPage enum in settings.h */
659 nb
= gtk_notebook_new();
660 gtk_notebook_append_page(GTK_NOTEBOOK(nb
), uisettings(jw
), gtk_label_new_with_mnemonic(_("Interface")));
661 gtk_notebook_append_page(GTK_NOTEBOOK(nb
), systemsettings(jw
), gtk_label_new_with_mnemonic(_("System")));
662 if (JAM_ACCOUNT_IS_LJ(jw
->account
)) gtk_notebook_append_page(GTK_NOTEBOOK(nb
), cfriendssettings(app
.cfmgr
), gtk_label_new_with_mnemonic(_("Check Friends")));
663 gtk_notebook_append_page(GTK_NOTEBOOK(nb
), debugsettings(dlg
), gtk_label_new_with_mnemonic(_("Debug")));
665 jam_dialog_set_contents(GTK_DIALOG(dlg
), nb
);
667 /* XXX HACK: set_contents calls show_all, but the "command"
668 * settings widgets sometimes want to have hidden children.
669 * so we let them rehide. */
670 for (SettingsWidget
*sw
= settingswidgets
; sw
->name
; ++sw
) if (sw
->type
== SW_COMMAND
) command_changed_cb(GTK_OPTION_MENU(sw
->widget
), sw
);
672 gtk_dialog_run(GTK_DIALOG(dlg
));
673 gtk_widget_destroy(dlg
);
677 void settings_cf_run (CFMgr
*cfm
) {
679 dlg
= gtk_dialog_new_with_buttons(_("Checkfriends Preferences"), NULL
/* no parent */ , GTK_DIALOG_MODAL
, GTK_STOCK_CLOSE
, GTK_RESPONSE_CLOSE
, NULL
);
680 jam_dialog_set_contents(GTK_DIALOG(dlg
), cfriendssettings(cfm
));
681 gtk_dialog_run(GTK_DIALOG(dlg
));
682 gtk_widget_destroy(dlg
);
686 void settings_run (JamWin
*jw
) {
689 gboolean hadspell = conf.options.usespellcheck;
692 gboolean hadautosave
= conf
.options
.autosave
;
693 gboolean hadquotes
= conf
.options
.smartquotes
;
695 run_settings_dialog(jw
);
697 g_slist_foreach(app
.secmgr_list
, (GFunc
) secmgr_security_set_force
, &conf
.defaultsecurity
);
699 cf_threshold_normalize(&conf
.cfthreshold
);
701 if (!hadautosave
&& conf
.options
.autosave
) jam_autosave_init(jw
);
702 if (hadautosave
&& !conf
.options
.autosave
) jam_autosave_stop(jw
);
704 if (conf
.options
.allowmultipleinstances
) {
706 if (!logjam_remote_stop_listening(app
.remote
, &err
)) {
707 jam_warning(GTK_WINDOW(jw
), _("Error stopping remote listener: %s."), err
->message
);
711 if (!conf
.options
.allowmultipleinstances
) {
713 if (!logjam_remote_listen(app
.remote
, &err
) && err
) {
714 jam_warning(GTK_WINDOW(jw
), _("Error starting remote listener: %s."), err
->message
);
719 if (hadquotes
) smartquotes_detach(jam_doc_get_text_buffer(jw
->doc
));
720 if (conf
.options
.smartquotes
) smartquotes_attach(jam_doc_get_text_buffer(jw
->doc
), conf
.options
.smartquotes_russian
);
722 jam_view_settings_changed(jam_win_get_cur_view(jw
));
726 static void run_cfmask_settings_dlg (SettingsWidget
*sw
) {
727 GtkWindow
*window
= GTK_WINDOW(gtk_widget_get_toplevel(sw
->widget
));
728 JamAccountLJ
*acc
= sw
->conf
;
729 jam_account_lj_set_cfmask(acc
, custom_security_dlg_run(window
, jam_account_lj_get_cfmask(acc
), acc
));