1 /* logjam - a GTK client for LiveJournal.
2 * Copyright (C) 2000-2004 Evan Martin <martine@danga.com>
4 * vim: tabstop=4 shiftwidth=4 noexpandtab :
17 #include "checkfriends.h"
26 static const gchar
*cf_help
= N_(
27 "The Check Friends feature is enabled by right-clicking on this "
28 "button and selecting \"Check friends view for new entries\". Once "
29 "you do so, you will be notified every time one of your friends "
30 "updates their journal with a new entry.\n\n"
32 "Once this happens, the indicator will turn red. You can then "
33 "read your friends page (as a convenience, double-clicking on "
34 "the indicator will take you there). Click on the indicator once "
35 "you've read the new entries to resume monitoring for newer "
38 static void cf_dock_destroy(CFFloat
*cff
);
40 static void cf_dock_destroyed_cb(GtkWidget
*widget
, CFFloat
*cff
);
41 static void cf_float_destroyed_cb(GtkWidget
*widget
, CFFloat
*cff
);
44 cf_float_update(CFFloat
*cff
, CFState state
) {
45 const gchar
*tip_text
= NULL
;
49 throbber_stop(THROBBER(cff
->throbber
));
50 throbber_reset(THROBBER(cff
->throbber
));
51 tip_text
= _("Check Friends disabled");
54 throbber_stop(THROBBER(cff
->throbber
));
55 throbber_reset(THROBBER(cff
->throbber
));
56 tip_text
= _("No new entries in your friends view");
59 throbber_start(THROBBER(cff
->throbber
));
60 tip_text
= _("There are new entries in your friends view");
64 gtk_tooltips_set_tip(app
.tooltips
, cff
->box
, tip_text
, _(cf_help
));
68 cf_toggle_cb(GtkMenuItem
*mi
, CFFloat
* cff
) {
69 CFMgr
*cfm
= cff
->cfmgr
;
70 CFState state
= cfmgr_get_state(cfm
);
74 cfmgr_set_state(cfm
, CF_ON
);
78 cfmgr_set_state(cfm
, CF_DISABLED
);
84 open_friends_list(CFMgr
*cfm
) {
88 acc
= cfmgr_get_account(cfm
);
91 url
= g_strdup_printf("%s/users/%s/friends",
92 jam_account_lj_get_server(acc
)->url
,
93 jam_account_lj_get_user(acc
)->username
);
94 spawn_url(NULL
/* XXX parent */, url
);
99 cf_context_menu(CFFloat
* cff
, GdkEventButton
*ev
) {
100 CFMgr
*cfm
= cff
->cfmgr
;
101 CFState state
= cfmgr_get_state(cfm
);
103 GtkAccelGroup
*accelgroup
= gtk_accel_group_new();
104 GtkWidget
*cfmenu
= gtk_menu_new();
107 { /* Check friends on/off */
108 item
= gtk_check_menu_item_new_with_mnemonic(
109 _("_Check friends view for new entries"));
110 gtk_menu_shell_append(GTK_MENU_SHELL(cfmenu
), item
);
111 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item
),
112 (state
!= CF_DISABLED
));
113 g_signal_connect(G_OBJECT(item
), "activate",
114 G_CALLBACK(cf_toggle_cb
), cff
);
115 gtk_widget_show(item
);
119 item
= gtk_separator_menu_item_new();
120 gtk_menu_shell_append(GTK_MENU_SHELL(cfmenu
), item
);
121 gtk_widget_show(item
);
124 { /* Preferences... */
125 item
= gtk_image_menu_item_new_from_stock(GTK_STOCK_PREFERENCES
,
127 gtk_menu_shell_append(GTK_MENU_SHELL(cfmenu
), item
);
128 g_signal_connect_swapped(G_OBJECT(item
), "activate",
129 G_CALLBACK(settings_cf_run
), cfm
);
130 gtk_widget_show(item
);
133 { /* open friends list in browser */
134 item
= gtk_image_menu_item_new_with_mnemonic(
135 _("_Open friends list in browser"));
136 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item
),
137 gtk_image_new_from_stock(GTK_STOCK_JUMP_TO
, GTK_ICON_SIZE_MENU
));
138 gtk_menu_shell_append(GTK_MENU_SHELL(cfmenu
), item
);
139 g_signal_connect_swapped(G_OBJECT(item
), "activate",
140 G_CALLBACK(open_friends_list
), cfm
);
141 gtk_widget_show_all(item
);
144 gtk_menu_popup(GTK_MENU(cfmenu
), NULL
, NULL
, NULL
, NULL
,
145 ev
->button
, ev
->time
);
150 clicked_cb(GtkWidget
* w
, GdkEventButton
*ev
, CFFloat
*cff
) {
151 CFMgr
*cfm
= cff
->cfmgr
;
152 CFState state
= cfmgr_get_state(cfm
);
154 /* right-clicks start context menu (note: this case is terminal) */
155 if (ev
->button
== 3) {
156 cf_context_menu(cff
, ev
);
160 /* *all* left-clicks move CF_NEW to CF_ON */
162 cfmgr_set_state(cfm
, CF_ON
);
164 if (ev
->button
== 2) // XXX testing
165 cfmgr_set_state(cfm
, CF_NEW
);
168 /* and double-clicks open up the browser, too */
169 if (ev
->type
==GDK_2BUTTON_PRESS
) {
170 // XXX open_friends_list(GTK_WINDOW(cff->parent));
175 /* this help box will only be called once in a double-click,
176 * thankfully, because the above is terminal on double-clicks. */
177 /*if (state == CF_DISABLED) {
178 jam_message(GTK_WINDOW(cff->parent), JAM_MSG_INFO, TRUE,
179 _("Check Friends"), _(cf_help));
186 cf_float_state_changed_cb(CFMgr
*cfm
, CFState state
, CFFloat
*cff
) {
187 cf_float_update(cff
, state
);
189 /* autoraise if necessary */
190 if (state
== CF_NEW
&& conf
.options
.cffloatraise
)
191 gtk_window_present(GTK_WINDOW(cff
->win
));
195 cf_float_new(CFMgr
*cfm
) {
198 cff
= g_new0(CFFloat
, 1);
201 g_signal_connect(G_OBJECT(cfm
), "state_changed",
202 G_CALLBACK(cf_float_state_changed_cb
), cff
);
204 cff
->win
= gtk_window_new(GTK_WINDOW_TOPLEVEL
);
205 g_signal_connect(G_OBJECT(cff
->win
), "destroy",
206 G_CALLBACK(cf_float_destroyed_cb
), cff
);
207 gtk_window_set_wmclass(GTK_WINDOW(cff
->win
),
208 "logjam-checkfriends", "logjam-checkfriends");
209 geometry_tie(cff
->win
, GEOM_CFFLOAT
);
211 cff
->box
= gtk_event_box_new();
212 gtk_container_set_border_width(GTK_CONTAINER(cff
->box
), 3);
213 g_signal_connect(G_OBJECT(cff
->box
), "button_press_event",
214 G_CALLBACK(clicked_cb
), cff
);
216 cff
->throbber
= throbber_new();
217 gtk_container_add(GTK_CONTAINER(cff
->box
), cff
->throbber
);
219 if (!conf
.options
.cffloat_decorate
) {
220 GtkWidget
*frame
= gtk_frame_new(NULL
);
221 gtk_frame_set_shadow_type(GTK_FRAME(frame
), GTK_SHADOW_OUT
);
222 gtk_container_add(GTK_CONTAINER(cff
->win
), frame
);
223 gtk_container_add(GTK_CONTAINER(frame
), cff
->box
);
224 gtk_window_set_decorated(GTK_WINDOW(cff
->win
), FALSE
);
226 gtk_container_add(GTK_CONTAINER(cff
->win
), cff
->box
);
228 cf_float_update(cff
, cfmgr_get_state(cfm
));
229 gtk_widget_show_all(cff
->win
);
235 cf_update_dock(CFMgr
*cfm
, GtkWindow
* parent
) {
236 if (!conf
.options
.docklet
&& app
.docklet
) {
237 cf_dock_destroy(app
.docklet
);
238 } else if (conf
.options
.docklet
&& !app
.docklet
) {
239 app
.docklet
= cf_float_new(cfm
);
245 cf_float_destroyed_cb(GtkWidget
*widget
, CFFloat
*cff
) {
246 CFMgr
*cfm
= cff
->cfmgr
;
248 g_signal_handlers_disconnect_matched(cfm
,
255 cf_float_destroy(CFFloat
*cff
) {
256 /*CFMgr *cfm = cff->cfmgr;*/
258 if (GTK_IS_WIDGET(cff
->win
))
259 gtk_widget_destroy(cff
->win
);
265 cf_app_update_float(void) {
266 if (!conf
.options
.cffloat
&& app
.cf_float
) {
267 cf_float_destroy(app
.cf_float
);
269 } else if (conf
.options
.cffloat
&& !app
.cf_float
) {
270 app
.cf_float
= cf_float_new(app
.cfmgr
);
274 /* Docklet code based on docklet plugin for Gaim, copyright Robert McQueen */
277 cf_dock_destroy(CFFloat
*cff
) {
278 /*CFMgr *cfm = cff->cfmgr;*/
280 g_signal_handlers_disconnect_by_func(G_OBJECT(cff
->win
),
281 G_CALLBACK(cf_dock_destroyed_cb
), NULL
);
282 gtk_widget_destroy(GTK_WIDGET(cff
->win
));
288 cf_dock_destroyed_cb(GtkWidget
*widget
, CFFloat
*cff
) {
294 cf_dock_setup(CFFloat *ind) {
295 GtkWidget *docklet = app.docklet;
297 g_signal_connect(G_OBJECT(docklet), "destroy",
298 G_CALLBACK(cf_dock_destroyed_cb), ind);
300 gtk_container_add(GTK_CONTAINER(docklet), ind->box);
301 gtk_widget_show_all(GTK_WIDGET(docklet));
306 #endif /* USE_DOCK */
308 void cf_float_decorate_refresh(void) {
309 /* suck a bunch of events in. */
310 while (gtk_events_pending())
311 gtk_main_iteration();
314 gtk_window_set_decorated(GTK_WINDOW(app
.cf_float
->win
),
315 conf
.options
.cffloat_decorate
);
316 gtk_widget_hide(app
.cf_float
->win
);
317 gtk_widget_show(app
.cf_float
->win
);