1 /* logjam - a GTK client for LiveJournal.
2 * Copyright (C) 2000-2003 Evan Martin <evan@livejournal.com>
4 * vim: tabstop=4 shiftwidth=4 noexpandtab :
8 #include <stdlib.h> /* atoi */
16 #include "checkfriends.h"
19 #include "groupedbox.h"
21 #include "smartquotes.h"
27 /* what's this? all of these funny structures in the settings box?
28 * well, instead of creating and tearing down all of these widgets, i
29 * try to pull out shared functionality.
31 * it's loosely inspired by george lebl's pong
32 * http://www.5z.com/jirka/pong-documentation/
33 * but i've never actaully read how that works.
36 * we have a collection of SettingsWidgets that track their name and
37 * configuration option, and then it's all nicely automated through functions
52 typedef struct _SettingsWidget SettingsWidget
;
53 struct _SettingsWidget
{
56 SettingsWidgetType type
;
58 gpointer data
; /* extra pointer, to be used as needed. */
59 gpointer data2
; /* extra pointer for wimps. */
64 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:") },
89 { "ui_docklet", &conf
.options
.docklet
,
90 SW_TOGGLE
, N_("Add icon to system _tray (for GNOME/KDE/etc. dock)") },
94 { "web_spawn", &conf
.spawn_command
,
95 SW_COMMAND
, N_("Web browser:"), (gpointer
)spawn_commands
},
97 { "music_command", &conf
.music_command
,
98 SW_COMMAND
, N_("Detect music from:"), (gpointer
)music_commands
},
100 { "net_useproxy", &conf
.options
.useproxy
,
101 SW_TOGGLE
, N_("Use _proxy server") },
102 { "net_proxy", &conf
.proxy
,
103 SW_TEXT
, N_("UR_L:") },
105 { "net_useproxyauth", &conf
.options
.useproxyauth
,
106 SW_TOGGLE
, N_("Use proxy _authentication") },
107 { "net_proxyuser", &conf
.proxyuser
,
108 SW_TEXT
, N_("_User:") },
109 { "net_proxypass", &conf
.proxypass
,
110 SW_TEXT
, N_("_Password:") },
113 { "debug_netdump", &conf
.options
.netdump
,
114 SW_TOGGLE
, N_("Dump _network data on stderr") },
116 { "debug_nofork", &conf
.options
.nofork
,
117 SW_TOGGLE
, N_("Don't _fork on network requests") },
119 { "debug_nofork", &conf
.options
.nofork
,
120 SW_TOGGLE
, N_("Don't run network requests in a separate _thread") },
124 { "cf_autostart", &conf
.options
.cfautostart
,
125 SW_TOGGLE
, N_("_Monitor friends list for new entries upon login") },
126 { "cf_usemask", &conf
.options
.cfusemask
,
127 SW_TOGGLE
, N_("_Limit monitoring to groups of friends") },
128 { "cf_mask", NULL
/* set at runtime to that of current user */,
130 { "cf_userinterval", &conf
.cfuserinterval
,
131 SW_SPIN_INTEGER
, N_("_Check friends list every " /* X seconds */) },
132 { "cf_threshold", &conf
.cfthreshold
,
133 SW_SPIN_INTEGER
, N_("_Notify me after " /* X new entires */) },
134 { "cf_float", &conf
.options
.cffloat
,
135 SW_TOGGLE
, N_("_Floating indicator") },
136 { "cf_floatraise", &conf
.options
.cffloatraise
,
137 SW_TOGGLE
, N_("_Raise floating indicator when new entries detected") },
138 { "cf_float_decorate", &conf
.options
.cffloat_decorate
,
139 SW_TOGGLE
, N_("Show _titlebar on floating indicator") },
144 static SettingsWidget
*
145 sw_lookup(char *name
) {
147 for (sw
= settingswidgets
; sw
->name
; sw
++)
148 if (strcmp(name
, sw
->name
) == 0) return sw
;
149 g_error("sw_lookup failed for %s", name
);
154 toggle_enable_cb(GtkWidget
*toggle
, GtkWidget
*target
) {
155 gtk_widget_set_sensitive(target
,
156 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toggle
)));
159 toggle_tie_enable(GtkWidget
*toggle
, GtkWidget
*target
) {
160 gtk_widget_set_sensitive(target
,
161 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toggle
)));
162 g_signal_connect(G_OBJECT(toggle
), "toggled",
163 G_CALLBACK(toggle_enable_cb
), target
);
167 toggle_tie(SettingsWidget
*sw
) {
168 tie_toggle(GTK_TOGGLE_BUTTON(sw
->widget
), (gboolean
*)sw
->conf
);
172 radio_tie_cb(GtkToggleButton
*toggle
, SettingsWidget
*sw
) {
173 if (gtk_toggle_button_get_active(toggle
))
174 *(int*)sw
->conf
= GPOINTER_TO_INT(sw
->data
);
177 radio_tie(SettingsWidget
*sw
) {
178 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(sw
->widget
),
179 *(gint
*)sw
->conf
== GPOINTER_TO_INT(sw
->data
));
180 g_signal_connect(G_OBJECT(sw
->widget
), "toggled",
181 G_CALLBACK(radio_tie_cb
), sw
);
185 text_tie(SettingsWidget
*sw
) {
186 tie_text(GTK_ENTRY(sw
->widget
), (char**)sw
->conf
);
190 integer_tie_cb(GtkEditable
*e
, SettingsWidget
*sw
) {
191 char *text
= gtk_editable_get_chars(e
, 0, -1);
192 *(int*)sw
->conf
= atoi(text
);
196 integer_tie(SettingsWidget
*sw
) {
198 sprintf(buf
, "%d", *(int*)sw
->conf
);
199 gtk_entry_set_text(GTK_ENTRY(sw
->widget
), buf
);
200 g_signal_connect(G_OBJECT(sw
->widget
), "changed",
201 G_CALLBACK(integer_tie_cb
), sw
);
205 spin_integer_tie_cb(GtkSpinButton
*b
, SettingsWidget
*sw
) {
206 *(gint
*)sw
->conf
= (gint
)gtk_spin_button_get_value(b
);
209 spin_integer_tie(SettingsWidget
*sw
) {
210 g_signal_connect(G_OBJECT(sw
->widget
), "value-changed",
211 G_CALLBACK(spin_integer_tie_cb
), sw
);
215 combo_tie(SettingsWidget
*sw
) {
216 tie_combo(GTK_COMBO(sw
->widget
), (char**)sw
->conf
);
221 command_changed_cb(GtkOptionMenu
*omenu
, SettingsWidget
*sw
) {
222 CommandList
*cmds
= sw
->data
;
223 int cur
= gtk_option_menu_get_history(GTK_OPTION_MENU(sw
->widget
));
225 jam_widget_set_visible(sw
->data2
, cmds
[cur
].label
== NULL
);
226 if (cmds
[cur
].label
!= NULL
) {
227 const char *cmd
= cmds
[cur
].command
;
228 string_replace((char**)sw
->conf
, cmd
? g_strdup(cmd
) : NULL
);
229 gtk_entry_set_text(GTK_ENTRY(sw
->subwidget
), cmd
? cmd
: "");
234 command_make(SettingsWidget
*sw
) {
235 CommandList
*cmds
= sw
->data
;
236 GtkWidget
*vbox
, *menu
;
238 char *cmd
= *((char**)sw
->conf
);
242 menu
= gtk_menu_new();
243 for (i
= 0; cmds
[i
].label
; i
++) {
244 char *curcmd
= cmds
[i
].command
;
245 gtk_menu_shell_append(GTK_MENU_SHELL(menu
),
246 gtk_menu_item_new_with_label(_(cmds
[i
].label
)));
249 (cmd
&& curcmd
&& (strcmp(cmd
, curcmd
) == 0))))
252 gtk_menu_shell_append(GTK_MENU_SHELL(menu
),
253 gtk_menu_item_new_with_label(_("Custom Command")));
254 if (cur
== -1) cur
= i
;
256 sw
->widget
= gtk_option_menu_new();
257 gtk_option_menu_set_menu(GTK_OPTION_MENU(sw
->widget
), menu
);
258 gtk_option_menu_set_history(GTK_OPTION_MENU(sw
->widget
), cur
);
260 sw
->subwidget
= gtk_entry_new();
261 tie_text(GTK_ENTRY(sw
->subwidget
), (char**)sw
->conf
);
263 g_signal_connect(G_OBJECT(sw
->widget
), "changed",
264 G_CALLBACK(command_changed_cb
), sw
);
265 jam_widget_set_visible(sw
->subwidget
, cur
== i
);
267 sg
= gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL
);
268 vbox
= gtk_vbox_new(FALSE
, 3);
269 gtk_box_pack_start(GTK_BOX(vbox
),
270 labelled_box_new_sg(_(sw
->caption
), sw
->widget
, sg
),
272 sw
->data2
= labelled_box_new_sg(NULL
, sw
->subwidget
, sg
); /* ugh. */
273 gtk_box_pack_start(GTK_BOX(vbox
),
280 sw_make_sg(char *name
, GtkSizeGroup
*sg
) {
281 SettingsWidget
*sw
= sw_lookup(name
);
284 sw
->widget
= gtk_check_button_new_with_mnemonic(_(sw
->caption
));
288 sw
->widget
= gtk_radio_button_new_with_mnemonic(NULL
,
293 sw
->widget
= gtk_entry_new();
295 return labelled_box_new_sg(_(sw
->caption
), sw
->widget
, sg
);
297 sw
->widget
= gtk_entry_new();
298 gtk_entry_set_width_chars(GTK_ENTRY(sw
->widget
), 4);
300 return labelled_box_new(_(sw
->caption
), sw
->widget
);
301 case SW_SPIN_INTEGER
:
303 gdouble default_value
= *(gint
*)sw
->conf
;
304 GtkObject
*adj
= gtk_adjustment_new(default_value
,
305 /* client code should override these */
306 G_MINDOUBLE
, G_MAXDOUBLE
, 1.0, 1.0, 1.0);
307 sw
->widget
= gtk_spin_button_new(GTK_ADJUSTMENT(adj
), 1, 1);
309 spin_integer_tie(sw
);
310 return labelled_box_new_expand(_(sw
->caption
), sw
->widget
, FALSE
);
312 sw
->widget
= gtk_combo_new();
314 return labelled_box_new(_(sw
->caption
), sw
->widget
);
316 return command_make(sw
);
318 if (sw
->caption
&& sw
->widget
)
319 return labelled_box_new(_(sw
->caption
), sw
->widget
);
327 sw_make(char *name
) {
328 return sw_make_sg(name
, NULL
);
332 sec_changed_cb(SecMgr
*sm
, SettingsWidget
*sw
) {
333 secmgr_security_get(sm
, (LJSecurity
*)sw
->conf
);
337 run_fontsel_settings_dlg(SettingsWidget
*sw
) {
339 const gchar
*newfont
;
342 dlg
= gtk_font_selection_dialog_new(_("Select font"));
343 gtk_font_selection_dialog_set_font_name(GTK_FONT_SELECTION_DIALOG(dlg
),
344 gtk_label_get_text(GTK_LABEL(sw
->widget
)));
346 if (gtk_dialog_run(GTK_DIALOG(dlg
)) == GTK_RESPONSE_OK
) {
347 gtk_label_set_text(GTK_LABEL(sw
->widget
),
348 gtk_font_selection_dialog_get_font_name(
349 GTK_FONT_SELECTION_DIALOG(dlg
)));
353 newfont
= gtk_label_get_text(GTK_LABEL(sw
->widget
));
354 oldfont
= pango_font_description_to_string(
355 pango_context_get_font_description(
356 gtk_widget_get_pango_context(GTK_WIDGET(sw
->data
))));
358 if (newfont
&& g_ascii_strcasecmp(oldfont
, newfont
) != 0) {
359 string_replace(sw
->conf
, g_strdup(newfont
));
360 jam_widget_set_font(sw
->widget
, newfont
);
361 jam_widget_set_font(sw
->data
, newfont
);
365 gtk_widget_destroy(dlg
);
369 void docklet_enable(GtkWidget
*win
, gboolean enable
);
371 docklet_change_cb(GtkToggleButton
*tb
, JamWin
*jw
) {
372 docklet_enable(GTK_WIDGET(jw
), gtk_toggle_button_get_active(tb
));
374 #endif /* USE_DOCK */
377 uisettings(JamWin
*jw
) {
379 GtkWidget
*vbox
, *hbox
, *button
;
380 char *fontname
= NULL
;
381 GtkWidget
*post
, *entry
, *misc
;
383 vbox
= gtk_vbox_new(FALSE
, 18);
384 gtk_container_set_border_width(GTK_CONTAINER(vbox
), 10);
386 post
= groupedbox_new_with_text(_("Posting"));
387 gtk_box_pack_start(GTK_BOX(vbox
), post
, FALSE
, FALSE
, 0);
389 groupedbox_pack(GROUPEDBOX(post
),
390 sw_make("ui_revertusejournal"), FALSE
);
392 sw
= sw_lookup("ui_defaultsecurity");
393 sw
->widget
= secmgr_new(FALSE
);
394 secmgr_security_set(SECMGR(sw
->widget
), (LJSecurity
*)sw
->conf
);
395 g_signal_connect(G_OBJECT(sw
->widget
), "changed",
396 G_CALLBACK(sec_changed_cb
), sw
);
397 groupedbox_pack(GROUPEDBOX(post
), sw_make("ui_defaultsecurity"), FALSE
);
399 entry
= groupedbox_new_with_text(_("Entries"));
400 gtk_box_pack_start(GTK_BOX(vbox
), entry
, FALSE
, FALSE
, 0);
402 groupedbox_pack(GROUPEDBOX(entry
), sw_make("ui_autosave"), FALSE
);
406 GtkWidget
*toggle
= sw_make("ui_spellcheck");
407 GtkWidget
*label
, *box
;
409 hbox
= sw_make("ui_spell_language");
410 label
= gtk_label_new(" ");
411 gtk_box_pack_start(GTK_BOX(hbox
), label
, FALSE
, FALSE
, 0);
412 gtk_box_reorder_child(GTK_BOX(hbox
), label
, 0);
414 sw
= sw_lookup("ui_spell_language");
415 gtk_entry_set_width_chars(GTK_ENTRY(sw
->widget
), 5);
417 box
= gtk_vbox_new(FALSE
, 3);
418 gtk_box_pack_start(GTK_BOX(box
), toggle
, FALSE
, FALSE
, 0);
419 gtk_box_pack_start(GTK_BOX(box
), hbox
, FALSE
, FALSE
, 0);
421 groupedbox_pack(GROUPEDBOX(entry
), box
, FALSE
);
422 toggle_tie_enable(toggle
, hbox
);
426 groupedbox_pack(GROUPEDBOX(entry
),
427 sw_make("ui_smartquotes"), FALSE
);
428 groupedbox_pack(GROUPEDBOX(entry
),
429 sw_make("ui_smartquotes_ru"), FALSE
);
431 sw
= sw_lookup("ui_font");
432 if (conf
.uifont
== NULL
) {
433 fontname
= pango_font_description_to_string(
434 pango_context_get_font_description(
435 gtk_widget_get_pango_context(jw
->view
)));
436 sw
->widget
= gtk_label_new(fontname
? fontname
: _("[gtk default]"));
438 jam_widget_set_font(sw
->widget
, fontname
);
441 sw
->widget
= gtk_label_new(conf
.uifont
);
442 jam_widget_set_font(sw
->widget
, conf
.uifont
);
444 button
= gtk_button_new_from_stock(GTK_STOCK_SELECT_FONT
);
447 hbox
= labelled_box_new_expand(_(sw
->caption
), button
, FALSE
);
448 gtk_box_pack_start(GTK_BOX(hbox
), sw
->widget
, TRUE
, TRUE
, 0);
449 gtk_box_reorder_child(GTK_BOX(hbox
), sw
->widget
, 1);
451 groupedbox_pack(GROUPEDBOX(entry
), hbox
, FALSE
);
452 g_signal_connect_swapped(G_OBJECT(button
), "clicked",
453 G_CALLBACK(run_fontsel_settings_dlg
), sw
);
455 misc
= groupedbox_new_with_text(_("Behavior"));
456 gtk_box_pack_start(GTK_BOX(vbox
), misc
, FALSE
, FALSE
, 0);
458 groupedbox_pack(GROUPEDBOX(misc
),
459 sw_make("ui_allowmultipleinstances"), FALSE
);
462 button
= sw_make("ui_docklet");
463 g_signal_connect(G_OBJECT(button
), "toggled",
464 G_CALLBACK(docklet_change_cb
), jw
);
465 groupedbox_pack(GROUPEDBOX(misc
), button
, FALSE
);
466 #endif /* USE_DOCK */
477 vbox
= gtk_vbox_new(FALSE
, 6);
479 sg
= gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL
);
481 gtk_box_pack_start(GTK_BOX(vbox
),
482 sw_make_sg("net_proxyuser", sg
), FALSE
, FALSE
, 0);
483 gtk_box_pack_start(GTK_BOX(vbox
),
484 sw_make_sg("net_proxypass", sg
), FALSE
, FALSE
, 0);
490 music_diagnose(GtkWidget
*button
) {
491 GtkWindow
*dlg
= GTK_WINDOW(gtk_widget_get_toplevel(button
));
493 char *music
, *result
;
494 MusicSource source
= music_current_source();
496 if (!music_can_detect(&err
)) {
497 jam_warning(dlg
, "%s", err
->message
);
502 music
= music_detect(&err
);
504 if (source
== MUSIC_SOURCE_XMMS
&&
505 err
->domain
== G_SPAWN_ERROR
&& err
->code
== G_SPAWN_ERROR_NOENT
) {
506 jam_warning(dlg
, _("LogJam XMMS helper not found. "
507 "Did you install LogJam's XMMS support?"));
509 jam_warning(dlg
, _("Error detecting music: %s"), err
->message
);
514 result
= g_strdup_printf(_("Music detection succeeded.\n\nCurrent music:\n%s"), music
);
515 jam_messagebox(dlg
, _("Music Detection"), result
);
521 proxysettings(void) {
522 GtkWidget
*group
, *wbox
, *hbox
, *cb
, *table
, *authgroup
;
524 group
= groupedbox_new_with_text(_("Proxy"));
526 cb
= sw_make("net_useproxy");
527 groupedbox_pack(GROUPEDBOX(group
), cb
, FALSE
);
529 wbox
= gtk_vbox_new(FALSE
, 6);
530 toggle_tie_enable(cb
, wbox
);
531 groupedbox_pack(GROUPEDBOX(group
), wbox
, FALSE
);
533 hbox
= sw_make("net_proxy");
534 gtk_box_pack_start(GTK_BOX(wbox
), hbox
, FALSE
, FALSE
, 0);
536 cb
= sw_make("net_useproxyauth");
537 gtk_box_pack_start(GTK_BOX(wbox
), cb
, FALSE
, FALSE
, 0);
539 table
= proxyuserpass();
540 authgroup
= groupedbox_new();
541 groupedbox_pack(GROUPEDBOX(authgroup
), table
, FALSE
);
542 gtk_box_pack_start(GTK_BOX(wbox
), authgroup
, FALSE
, FALSE
, 0);
544 toggle_tie_enable(cb
, table
);
550 programsettings(JamWin
*jw
) {
552 GtkWidget
*button
, *hbox
;
554 JamView
*jv
= jam_win_get_cur_view(jw
);
556 group
= groupedbox_new_with_text(_("Programs"));
557 groupedbox_pack(GROUPEDBOX(group
), sw_make("web_spawn"), FALSE
);
559 groupedbox_pack(GROUPEDBOX(group
), sw_make("music_command"), FALSE
);
560 sw
= sw_lookup("music_command");
561 g_signal_connect_swapped(G_OBJECT(sw
->widget
), "changed",
562 G_CALLBACK(jam_view_settings_changed
), jv
);
564 button
= gtk_button_new_with_mnemonic(_("_Diagnose"));
565 g_signal_connect(G_OBJECT(button
), "clicked",
566 G_CALLBACK(music_diagnose
), NULL
);
567 hbox
= labelled_box_new_expand(_("Diagnose problems detecting music:"),
569 groupedbox_pack(GROUPEDBOX(group
), hbox
, FALSE
);
575 systemsettings(JamWin
*jw
) {
578 vbox
= gtk_vbox_new(FALSE
, 18);
579 gtk_container_set_border_width(GTK_CONTAINER(vbox
), 10);
580 gtk_box_pack_start(GTK_BOX(vbox
), programsettings(jw
), FALSE
, FALSE
, 0);
581 gtk_box_pack_start(GTK_BOX(vbox
), proxysettings(), FALSE
, FALSE
, 0);
584 #endif /* G_OS_WIN32 */
587 debugsettings(GtkWidget
*dlg
) {
588 GtkWidget
*vbox
, *gb
;
590 vbox
= gtk_vbox_new(FALSE
, 18);
591 gtk_container_set_border_width(GTK_CONTAINER(vbox
), 10);
593 gb
= groupedbox_new_with_text(_("Network"));
594 gtk_box_pack_start(GTK_BOX(vbox
), gb
, FALSE
, FALSE
, 0);
596 groupedbox_pack(GROUPEDBOX(gb
), sw_make("debug_netdump"), FALSE
);
597 groupedbox_pack(GROUPEDBOX(gb
), sw_make("debug_nofork"), FALSE
);
603 cfriends_general_settings(JamAccountLJ
*acc
) {
604 GtkWidget
*general
, *b
, *w
;
607 general
= groupedbox_new_with_text(_("General"));
609 groupedbox_pack(GROUPEDBOX(general
), sw_make("cf_autostart"), FALSE
);
611 b
= sw_make("cf_threshold");
612 sw
= sw_lookup("cf_threshold");
614 jam_spin_button_set(GTK_SPIN_BUTTON(w
), TRUE
/* numeric */,
615 1.0, 7.0 /* range */, 1.0, 1.0 /*increments */, 0 /* digits */);
616 gtk_box_pack_start(GTK_BOX(b
),
617 gtk_label_new(_("new entries by my friends")), FALSE
, FALSE
, 5);
618 /* XXX: ugly, because it defaults to "1 entries". Yuck. */
619 groupedbox_pack(GROUPEDBOX(general
), b
, FALSE
);
621 b
= sw_make("cf_userinterval");
622 sw
= sw_lookup("cf_userinterval");
624 jam_spin_button_set(GTK_SPIN_BUTTON(w
), TRUE
/*numeric*/,
625 45.0, 3600.0 /*range*/, 1.0, 10.0 /*increments*/, 0 /*digits*/);
626 gtk_box_pack_start(GTK_BOX(b
), gtk_label_new(_("seconds")),
628 groupedbox_pack(GROUPEDBOX(general
), b
, FALSE
);
635 cfriends_filter_settings(JamAccountLJ
*acc
) {
636 GtkWidget
*filter
, *maskhbox
, *l
;
638 LJUser
*u
= jam_account_lj_get_user(acc
);
640 filter
= groupedbox_new_with_text(_("Filter"));
642 maskhbox
= gtk_hbox_new(FALSE
, 5);
643 gtk_box_pack_start(GTK_BOX(maskhbox
),
644 sw_make("cf_usemask"), FALSE
, FALSE
, 0);
645 sw
= sw_lookup("cf_mask");
647 sw
->widget
= gtk_button_new_with_label(_("Choose filter"));
648 gtk_box_pack_start(GTK_BOX(maskhbox
), GTK_WIDGET(sw
->widget
), FALSE
, FALSE
, 0);
649 gtk_widget_set_sensitive(sw
->widget
, u
->friendgroups
!= NULL
);
650 g_signal_connect_swapped(G_OBJECT(sw
->widget
), "clicked",
651 G_CALLBACK(run_cfmask_settings_dlg
), sw
);
652 l
= gtk_label_new(NULL
);
653 gtk_label_set_markup(GTK_LABEL(l
),
654 _("<small>The filter chosen here only affects the "
655 "current user.</small>"));
656 gtk_label_set_line_wrap(GTK_LABEL(l
), TRUE
);
657 gtk_label_set_justify(GTK_LABEL(l
), GTK_JUSTIFY_LEFT
);
659 groupedbox_pack(GROUPEDBOX(filter
), maskhbox
, FALSE
);
660 groupedbox_pack(GROUPEDBOX(filter
), l
, FALSE
);
666 float_change_cb(GtkWidget
*w
, CFMgr
*cfm
) {
667 cf_app_update_float();
671 cfriends_indicators_settings(CFMgr
*cfm
) {
672 GtkWidget
*indicators
, *floaters
, *b
, *w
;
675 indicators
= groupedbox_new_with_text(_("Indicators"));
677 b
= sw_make("cf_float");
678 g_signal_connect(G_OBJECT(b
), "toggled",
679 G_CALLBACK(float_change_cb
), cfm
);
680 sw
= sw_lookup("cf_float");
682 groupedbox_pack(GROUPEDBOX(indicators
), b
, FALSE
);
684 floaters
= groupedbox_new();
685 groupedbox_pack(GROUPEDBOX(indicators
), floaters
, FALSE
);
687 groupedbox_pack(GROUPEDBOX(floaters
), sw_make("cf_floatraise"), FALSE
);
688 b
= sw_make("cf_float_decorate");
689 g_signal_connect(G_OBJECT(b
), "toggled",
690 G_CALLBACK(cf_float_decorate_refresh
), NULL
);
691 groupedbox_pack(GROUPEDBOX(floaters
), b
, FALSE
);
693 toggle_tie_enable(w
, floaters
);
699 cfriendssettings(CFMgr
*cfm
) {
701 JamAccountLJ
*acc
= cfmgr_get_account(cfm
);
703 vbox
= gtk_vbox_new(FALSE
, 18);
704 gtk_container_set_border_width(GTK_CONTAINER(vbox
), 10);
707 gtk_box_pack_start(GTK_BOX(vbox
), cfriends_general_settings(acc
),
711 gtk_box_pack_start(GTK_BOX(vbox
), cfriends_filter_settings(acc
),
715 gtk_box_pack_start(GTK_BOX(vbox
), cfriends_indicators_settings(cfm
),
722 run_settings_dialog(JamWin
*jw
) {
725 dlg
= gtk_dialog_new_with_buttons(_("Preferences"),
726 GTK_WINDOW(jw
), GTK_DIALOG_MODAL
,
727 GTK_STOCK_CLOSE
, GTK_RESPONSE_CLOSE
,
730 /* the order of notebook pages created here should match the
731 * SettingsPage enum in settings.h */
732 nb
= gtk_notebook_new();
733 gtk_notebook_append_page(GTK_NOTEBOOK(nb
),
734 uisettings(jw
), gtk_label_new_with_mnemonic(_("Interface")));
736 gtk_notebook_append_page(GTK_NOTEBOOK(nb
),
737 systemsettings(jw
), gtk_label_new_with_mnemonic(_("System")));
738 #endif /* G_OS_WIN32 */
739 if (JAM_ACCOUNT_IS_LJ(jw
->account
))
740 gtk_notebook_append_page(GTK_NOTEBOOK(nb
),
741 cfriendssettings(app
.cfmgr
), gtk_label_new_with_mnemonic(_("Check Friends")));
742 gtk_notebook_append_page(GTK_NOTEBOOK(nb
),
743 debugsettings(dlg
), gtk_label_new_with_mnemonic(_("Debug")));
745 jam_dialog_set_contents(GTK_DIALOG(dlg
), nb
);
747 /* XXX HACK: set_contents calls show_all, but the "command"
748 * settings widgets sometimes want to have hidden children.
749 * so we let them rehide. */
752 for (sw
= settingswidgets
; sw
->name
; sw
++)
753 if (sw
->type
== SW_COMMAND
)
754 command_changed_cb(GTK_OPTION_MENU(sw
->widget
), sw
);
757 gtk_dialog_run(GTK_DIALOG(dlg
));
758 gtk_widget_destroy(dlg
);
762 settings_cf_run(CFMgr
*cfm
) {
765 dlg
= gtk_dialog_new_with_buttons(_("Checkfriends Preferences"),
766 NULL
/* no parent */, GTK_DIALOG_MODAL
,
767 GTK_STOCK_CLOSE
, GTK_RESPONSE_CLOSE
,
770 jam_dialog_set_contents(GTK_DIALOG(dlg
), cfriendssettings(cfm
));
772 gtk_dialog_run(GTK_DIALOG(dlg
));
773 gtk_widget_destroy(dlg
);
777 settings_run(JamWin
*jw
) {
780 gboolean hadspell = conf.options.usespellcheck;
783 gboolean hadautosave
= conf
.options
.autosave
;
784 gboolean hadquotes
= conf
.options
.smartquotes
;
786 run_settings_dialog(jw
);
788 g_slist_foreach(app
.secmgr_list
, (GFunc
)secmgr_security_set_force
,
789 &conf
.defaultsecurity
);
791 cf_threshold_normalize(&conf
.cfthreshold
);
793 if (!hadautosave
&& conf
.options
.autosave
)
794 jam_autosave_init(jw
);
795 if (hadautosave
&& !conf
.options
.autosave
)
796 jam_autosave_stop(jw
);
798 if (conf
.options
.allowmultipleinstances
) {
800 if (!logjam_remote_stop_listening(app
.remote
, &err
)) {
801 jam_warning(GTK_WINDOW(jw
),
802 _("Error stopping remote listener: %s."), err
->message
);
806 if (!conf
.options
.allowmultipleinstances
) {
808 if (!logjam_remote_listen(app
.remote
, &err
) && err
) {
809 jam_warning(GTK_WINDOW(jw
),
810 _("Error starting remote listener: %s."), err
->message
);
815 if (hadquotes
) smartquotes_detach(jam_doc_get_text_buffer(jw
->doc
));
816 if (conf
.options
.smartquotes
)
817 smartquotes_attach(jam_doc_get_text_buffer(jw
->doc
), conf
.options
.smartquotes_russian
);
819 jam_view_settings_changed(jam_win_get_cur_view(jw
));
823 run_cfmask_settings_dlg(SettingsWidget
*sw
) {
824 GtkWindow
*window
= GTK_WINDOW(gtk_widget_get_toplevel(sw
->widget
));
825 JamAccountLJ
*acc
= sw
->conf
;
826 jam_account_lj_set_cfmask(acc
,
827 custom_security_dlg_run(window
, jam_account_lj_get_cfmask(acc
), acc
));