1 /* logjam - a GTK client for LiveJournal.
2 * Copyright (C) 2000-2003 Evan Martin <evan@livejournal.com>
19 JamAccountLJ
*account
;
23 static void secmgr_init (SecMgr
*sm
);
25 static void security_changed (SecMgr
*sm
);
26 static void secmgr_destroyed_cb (GObject
*sm
);
29 static const LJSecurity security_private
= { LJ_SECURITY_PRIVATE
, 0 };
33 GType
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
, "SecMgr", &sm_info
, 0);
53 static GtkWidget
*add_menu_item (GtkMenuShell
*ms
, const gchar
*id
, const gchar
*text
) {
57 hbox
= gtk_hbox_new(FALSE
, 3);
58 gtk_box_pack_start(GTK_BOX(hbox
), gtk_image_new_from_stock(id
, GTK_ICON_SIZE_MENU
), FALSE
, FALSE
, 0);
59 gtk_box_pack_start(GTK_BOX(hbox
), gtk_label_new(text
), FALSE
, FALSE
, 0);
61 item
= gtk_menu_item_new();
62 gtk_container_add(GTK_CONTAINER(item
), hbox
);
63 gtk_menu_shell_append(ms
, item
);
68 static void secmgr_init (SecMgr
*sm
) {
72 menu
= gtk_menu_new();
73 ms
= GTK_MENU_SHELL(menu
);
75 add_menu_item(ms
, "logjam-ljuser", _("Public"));
76 add_menu_item(ms
, "logjam-protected", _("Friends"));
77 add_menu_item(ms
, "logjam-private", _("Private"));
78 sm
->custom
= add_menu_item(ms
, NULL
, _("Custom..."));
79 gtk_widget_set_sensitive(sm
->custom
, FALSE
);
81 gtk_widget_show_all(menu
);
82 gtk_option_menu_set_menu(GTK_OPTION_MENU(sm
), menu
);
84 gtk_option_menu_set_history(GTK_OPTION_MENU(sm
), sm
->security
.type
);
86 g_signal_connect(G_OBJECT(sm
), "changed", G_CALLBACK(security_changed
), NULL
);
89 app
.secmgr_list
= g_slist_append(app
.secmgr_list
, sm
);
90 /* g_signal_connect(G_OBJECT(sm), "destroy",
91 G_CALLBACK(g_slist_remove), sm);
93 wouldn't this have been nice? unfortunately, the return value of
94 g_slist_remove must be kept, so we have to wrap this in a function.
96 g_signal_connect(G_OBJECT(sm
), "destroy", G_CALLBACK(secmgr_destroyed_cb
), NULL
);
100 static void secmgr_destroyed_cb (GObject
*sm
) {
101 app
.secmgr_list
= g_slist_remove(app
.secmgr_list
, sm
);
105 GtkWidget
*secmgr_new (gboolean withcustom
) {
106 SecMgr
*sm
= SECMGR(g_object_new(secmgr_get_type(), NULL
));
107 if (!withcustom
) gtk_widget_destroy(sm
->custom
);
108 return GTK_WIDGET(sm
);
112 void secmgr_set_account (SecMgr
*sm
, JamAccountLJ
*account
) {
113 gtk_widget_set_sensitive(sm
->custom
, account
!= NULL
);
114 if (account
!= sm
->account
) {
116 sm
->account
= account
;
117 secmgr_security_get(sm
, &oldsec
);
118 if (oldsec
.type
== LJ_SECURITY_CUSTOM
) secmgr_security_set(sm
, &security_private
);
123 void secmgr_security_set (SecMgr
*secmgr
, const LJSecurity
*security
) {
124 secmgr
->security
= *security
;
125 gtk_option_menu_set_history(GTK_OPTION_MENU(secmgr
), secmgr
->security
.type
);
129 void secmgr_security_get (SecMgr
*secmgr
, LJSecurity
*security
) {
130 *security
= secmgr
->security
;
134 /* a version of secmgr_security_set that avoids emitting the "changed"
135 * signal. useful for programmatic adjustments to a SecMgr (such as applying
136 * a user's changes from the Settings dialog), in order to avoid running the
137 * custom security dialog again. It should *only* be used in cases where
138 * the "changed" handler has already dealt with this change, or the input is
139 * known to be good for some other reason. */
140 void secmgr_security_set_force (SecMgr
*secmgr
, const LJSecurity
*security
) {
141 g_signal_handlers_block_by_func(G_OBJECT(secmgr
), security_changed
, NULL
);
142 secmgr_security_set(secmgr
, security
);
143 g_signal_handlers_unblock_by_func(G_OBJECT(secmgr
), security_changed
, NULL
);
147 void security_changed (SecMgr
*sm
) {
148 sm
->security
.type
= gtk_option_menu_get_history(GTK_OPTION_MENU(sm
));
149 if (sm
->security
.type
== LJ_SECURITY_CUSTOM
) {
150 sm
->security
.allowmask
= custom_security_dlg_run(GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(sm
))), sm
->security
.allowmask
, sm
->account
);
152 sm
->security
.allowmask
= 0; /* reset it. */
154 if (sm
->security
.type
== LJ_SECURITY_CUSTOM
&& sm
->security
.allowmask
== 0) secmgr_security_set(sm
, &security_private
);
165 static void included_toggle_cb (GtkCellRendererToggle
*cell
, gchar
*path_str
, gpointer data
) {
166 GtkTreeModel
*model
= data
;
168 GtkTreePath
*path
= gtk_tree_path_new_from_string(path_str
);
171 gtk_tree_model_get_iter(model
, &iter
, path
);
172 gtk_tree_model_get(model
, &iter
, COL_INCLUDED
, &included
, -1);
174 included
= !included
;
176 gtk_list_store_set(GTK_LIST_STORE(model
), &iter
, COL_INCLUDED
, included
, -1);
177 gtk_tree_path_free(path
);
181 static GtkTreeModel
*build_model (guint32 mask
, LJUser
*user
) {
187 store
= gtk_list_store_new(3, G_TYPE_BOOLEAN
, /* included? */
188 G_TYPE_STRING
, /* name */
189 G_TYPE_POINTER
/* friendgroup */ );
190 for (l
= user
->friendgroups
; l
!= NULL
; l
= l
->next
) {
191 fg
= (LJFriendGroup
*) l
->data
;
192 gtk_list_store_append(store
, &iter
);
193 gtk_list_store_set(store
, &iter
, COL_INCLUDED
, ((1L << fg
->id
) & mask
) != 0, COL_NAME
, fg
->name
, COL_FG
, fg
, -1);
195 return GTK_TREE_MODEL(store
);
199 static GtkWidget
*build_view (GtkTreeModel
*model
) {
201 GtkCellRenderer
*renderer
;
202 GtkTreeViewColumn
*column
;
204 view
= gtk_tree_view_new_with_model(model
);
205 column
= gtk_tree_view_column_new();
206 gtk_tree_view_column_set_title(column
, _("Included Groups"));
208 renderer
= gtk_cell_renderer_toggle_new();
209 g_signal_connect(G_OBJECT(renderer
), "toggled", G_CALLBACK(included_toggle_cb
), model
);
210 gtk_tree_view_column_pack_start(column
, renderer
, FALSE
);
211 gtk_tree_view_column_add_attribute(column
, renderer
, "active", COL_INCLUDED
);
213 renderer
= gtk_cell_renderer_text_new();
214 gtk_tree_view_column_pack_start(column
, renderer
, TRUE
);
215 gtk_tree_view_column_add_attribute(column
, renderer
, "text", COL_NAME
);
217 gtk_tree_view_append_column(GTK_TREE_VIEW(view
), column
);
222 static guint32
get_new_mask (GtkTreeModel
*model
) {
228 if (gtk_tree_model_get_iter_first(model
, &iter
)) {
230 gtk_tree_model_get(model
, &iter
, COL_INCLUDED
, &included
, COL_FG
, &fg
, -1);
231 if (included
) newmask
|= (1L << fg
->id
);
232 } while (gtk_tree_model_iter_next(model
, &iter
));
238 guint32
custom_security_dlg_run (GtkWindow
*parent
, guint32 mask
, JamAccountLJ
*acc
) {
242 LJUser
*user
= jam_account_lj_get_user(acc
);
244 dlg
= gtk_dialog_new_with_buttons(_("Select Friend Groups"), parent
, GTK_DIALOG_MODAL
, GTK_STOCK_CLOSE
, GTK_RESPONSE_CLOSE
, NULL
);
245 jam_win_set_size(GTK_WINDOW(dlg
), 300, -1);
247 model
= build_model(mask
, user
);
248 view
= build_view(model
);
250 jam_dialog_set_contents(GTK_DIALOG(dlg
), scroll_wrap(view
));
252 gtk_dialog_run(GTK_DIALOG(dlg
));
253 mask
= get_new_mask(model
);
254 g_object_unref(G_OBJECT(model
));
255 gtk_widget_destroy(dlg
);