1 /* logjam - a GTK client for LiveJournal.
2 * Copyright (C) 2000-2003 Evan Martin <evan@livejournal.com>
4 * vim: tabstop=4 shiftwidth=4 noexpandtab :
21 JamAccountLJ
*account
;
24 static void secmgr_init(SecMgr
*sm
);
26 static void security_changed(SecMgr
*sm
);
27 static void secmgr_destroyed_cb(GObject
* sm
);
29 static const LJSecurity security_private
= { LJ_SECURITY_PRIVATE
, 0 };
33 secmgr_get_type(void) {
34 static GType sm_type
= 0;
36 const GTypeInfo sm_info
= {
37 sizeof (GtkOptionMenuClass
),
45 (GInstanceInitFunc
) secmgr_init
,
47 sm_type
= g_type_register_static(GTK_TYPE_OPTION_MENU
,
48 "SecMgr", &sm_info
, 0);
54 add_menu_item(GtkMenuShell
*ms
, const gchar
*id
, const gchar
*text
) {
58 hbox
= gtk_hbox_new(FALSE
, 3);
59 gtk_box_pack_start(GTK_BOX(hbox
),
60 gtk_image_new_from_stock(id
, GTK_ICON_SIZE_MENU
),
62 gtk_box_pack_start(GTK_BOX(hbox
),
63 gtk_label_new(text
), FALSE
, FALSE
, 0);
65 item
= gtk_menu_item_new();
66 gtk_container_add(GTK_CONTAINER(item
), hbox
);
67 gtk_menu_shell_append(ms
, item
);
72 secmgr_init(SecMgr
*sm
) {
76 menu
= gtk_menu_new();
77 ms
= GTK_MENU_SHELL(menu
);
79 add_menu_item(ms
, "logjam-ljuser", _("Public"));
80 add_menu_item(ms
, "logjam-protected", _("Friends"));
81 add_menu_item(ms
, "logjam-private", _("Private"));
82 sm
->custom
= add_menu_item(ms
, NULL
, _("Custom..."));
83 gtk_widget_set_sensitive(sm
->custom
, FALSE
);
85 gtk_widget_show_all(menu
);
86 gtk_option_menu_set_menu(GTK_OPTION_MENU(sm
), menu
);
88 gtk_option_menu_set_history(GTK_OPTION_MENU(sm
), sm
->security
.type
);
90 g_signal_connect(G_OBJECT(sm
), "changed",
91 G_CALLBACK(security_changed
), NULL
);
94 app
.secmgr_list
= g_slist_append(app
.secmgr_list
, sm
);
95 /* g_signal_connect(G_OBJECT(sm), "destroy",
96 G_CALLBACK(g_slist_remove), sm);
98 wouldn't this have been nice? unfortunately, the return value of
99 g_slist_remove must be kept, so we have to wrap this in a function.
101 g_signal_connect(G_OBJECT(sm
), "destroy",
102 G_CALLBACK(secmgr_destroyed_cb
), NULL
);
106 secmgr_destroyed_cb(GObject
* sm
) {
107 app
.secmgr_list
= g_slist_remove(app
.secmgr_list
, sm
);
111 secmgr_new(gboolean withcustom
) {
112 SecMgr
*sm
= SECMGR(g_object_new(secmgr_get_type(), NULL
));
114 gtk_widget_destroy(sm
->custom
);
115 return GTK_WIDGET(sm
);
119 secmgr_set_account(SecMgr
*sm
, JamAccountLJ
*account
) {
120 gtk_widget_set_sensitive(sm
->custom
, account
!= NULL
);
121 if (account
!= sm
->account
) {
124 sm
->account
= account
;
126 secmgr_security_get(sm
, &oldsec
);
127 if (oldsec
.type
== LJ_SECURITY_CUSTOM
)
128 secmgr_security_set(sm
, &security_private
);
133 secmgr_security_set(SecMgr
*secmgr
, const LJSecurity
*security
) {
134 secmgr
->security
= *security
;
135 gtk_option_menu_set_history(GTK_OPTION_MENU(secmgr
), secmgr
->security
.type
);
138 secmgr_security_get(SecMgr
*secmgr
, LJSecurity
*security
) {
139 *security
= secmgr
->security
;
142 /* a version of secmgr_security_set that avoids emitting the "changed"
143 * signal. useful for programmatic adjustments to a SecMgr (such as applying
144 * a user's changes from the Settings dialog), in order to avoid running the
145 * custom security dialog again. It should *only* be used in cases where
146 * the "changed" handler has already dealt with this change, or the input is
147 * known to be good for some other reason. */
149 secmgr_security_set_force(SecMgr
*secmgr
, const LJSecurity
*security
) {
150 g_signal_handlers_block_by_func(G_OBJECT(secmgr
),
151 security_changed
, NULL
);
152 secmgr_security_set(secmgr
, security
);
153 g_signal_handlers_unblock_by_func(G_OBJECT(secmgr
),
154 security_changed
, NULL
);
158 security_changed(SecMgr
*sm
) {
159 sm
->security
.type
= gtk_option_menu_get_history(GTK_OPTION_MENU(sm
));
160 if (sm
->security
.type
== LJ_SECURITY_CUSTOM
) {
161 sm
->security
.allowmask
=
162 custom_security_dlg_run(
163 GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(sm
))),
164 sm
->security
.allowmask
,
167 sm
->security
.allowmask
= 0; /* reset it. */
170 if (sm
->security
.type
== LJ_SECURITY_CUSTOM
171 && sm
->security
.allowmask
== 0) {
172 secmgr_security_set(sm
, &security_private
);
183 included_toggle_cb(GtkCellRendererToggle
*cell
,
184 gchar
*path_str
, gpointer data
) {
185 GtkTreeModel
*model
= data
;
187 GtkTreePath
*path
= gtk_tree_path_new_from_string(path_str
);
190 gtk_tree_model_get_iter(model
, &iter
, path
);
191 gtk_tree_model_get(model
, &iter
,
192 COL_INCLUDED
, &included
,
195 included
= !included
;
197 gtk_list_store_set(GTK_LIST_STORE(model
), &iter
,
198 COL_INCLUDED
, included
,
200 gtk_tree_path_free(path
);
204 build_model(guint32 mask
, LJUser
*user
) {
210 store
= gtk_list_store_new(3,
211 G_TYPE_BOOLEAN
, /* included? */
212 G_TYPE_STRING
, /* name */
213 G_TYPE_POINTER
/* friendgroup */);
214 for (l
= user
->friendgroups
; l
!= NULL
; l
= l
->next
) {
215 fg
= (LJFriendGroup
*)l
->data
;
216 gtk_list_store_append(store
, &iter
);
217 gtk_list_store_set(store
, &iter
,
218 COL_INCLUDED
, ((1L << fg
->id
) & mask
) != 0,
223 return GTK_TREE_MODEL(store
);
227 build_view(GtkTreeModel
*model
) {
229 GtkCellRenderer
*renderer
;
230 GtkTreeViewColumn
*column
;
232 view
= gtk_tree_view_new_with_model(model
);
233 column
= gtk_tree_view_column_new();
234 gtk_tree_view_column_set_title(column
, _("Included Groups"));
236 renderer
= gtk_cell_renderer_toggle_new();
237 g_signal_connect(G_OBJECT(renderer
), "toggled",
238 G_CALLBACK(included_toggle_cb
), model
);
239 gtk_tree_view_column_pack_start(column
, renderer
, FALSE
);
240 gtk_tree_view_column_add_attribute(column
, renderer
,
241 "active", COL_INCLUDED
);
243 renderer
= gtk_cell_renderer_text_new();
244 gtk_tree_view_column_pack_start(column
, renderer
, TRUE
);
245 gtk_tree_view_column_add_attribute(column
, renderer
,
248 gtk_tree_view_append_column(GTK_TREE_VIEW(view
), column
);
253 get_new_mask(GtkTreeModel
*model
) {
259 if (gtk_tree_model_get_iter_first(model
, &iter
)) {
261 gtk_tree_model_get(model
, &iter
,
262 COL_INCLUDED
, &included
,
266 newmask
|= (1L << fg
->id
);
267 } while (gtk_tree_model_iter_next(model
, &iter
));
273 custom_security_dlg_run(GtkWindow
*parent
, guint32 mask
, JamAccountLJ
*acc
) {
277 LJUser
*user
= jam_account_lj_get_user(acc
);
279 dlg
= gtk_dialog_new_with_buttons(_("Select Friend Groups"),
280 parent
, GTK_DIALOG_MODAL
,
281 GTK_STOCK_CLOSE
, GTK_RESPONSE_CLOSE
,
283 jam_win_set_size(GTK_WINDOW(dlg
), 300, -1);
285 model
= build_model(mask
, user
);
286 view
= build_view(model
);
288 jam_dialog_set_contents(GTK_DIALOG(dlg
), scroll_wrap(view
));
290 gtk_dialog_run(GTK_DIALOG(dlg
));
291 mask
= get_new_mask(model
);
292 g_object_unref(G_OBJECT(model
));
293 gtk_widget_destroy(dlg
);