1 /* logjam - a GTK client for LiveJournal.
2 * Copyright (C) 2000-2004 Evan Martin <martine@danga.com>
14 #include "checkfriends.h"
24 static const gchar
*cf_help
=
25 N_("The Check Friends feature is enabled by right-clicking on this "
26 "button and selecting \"Check friends view for new entries\". Once "
27 "you do so, you will be notified every time one of your friends "
28 "updates their journal with a new entry.\n\n"
29 "Once this happens, the indicator will turn red. You can then "
30 "read your friends page (as a convenience, double-clicking on "
31 "the indicator will take you there). Click on the indicator once "
32 "you've read the new entries to resume monitoring for newer " "entries.\n\n");
34 static void cf_dock_destroy (CFFloat
*cff
);
36 static void cf_dock_destroyed_cb (GtkWidget
*widget
, CFFloat
*cff
);
37 static void cf_float_destroyed_cb (GtkWidget
*widget
, CFFloat
*cff
);
40 static void cf_float_update (CFFloat
*cff
, CFState state
) {
41 const gchar
*tip_text
= NULL
;
44 throbber_stop(THROBBER(cff
->throbber
));
45 throbber_reset(THROBBER(cff
->throbber
));
46 tip_text
= _("Check Friends disabled");
49 throbber_stop(THROBBER(cff
->throbber
));
50 throbber_reset(THROBBER(cff
->throbber
));
51 tip_text
= _("No new entries in your friends view");
54 throbber_start(THROBBER(cff
->throbber
));
55 tip_text
= _("There are new entries in your friends view");
58 gtk_tooltips_set_tip(app
.tooltips
, cff
->box
, tip_text
, _(cf_help
));
62 static void cf_toggle_cb (GtkMenuItem
*mi
, CFFloat
*cff
) {
63 CFMgr
*cfm
= cff
->cfmgr
;
64 CFState state
= cfmgr_get_state(cfm
);
67 cfmgr_set_state(cfm
, CF_ON
);
71 cfmgr_set_state(cfm
, CF_DISABLED
);
77 static void open_friends_list (CFMgr
*cfm
) {
79 JamAccountLJ
*acc
= cfmgr_get_account(cfm
);
81 url
= g_strdup_printf("%s/users/%s/friends", jam_account_lj_get_server(acc
)->url
, jam_account_lj_get_user(acc
)->username
);
82 spawn_url(NULL
/* XXX parent */, url
);
87 void cf_context_menu (CFFloat
*cff
, GdkEventButton
*ev
) {
88 CFMgr
*cfm
= cff
->cfmgr
;
89 CFState state
= cfmgr_get_state(cfm
);
90 GtkAccelGroup
*accelgroup
= gtk_accel_group_new();
91 GtkWidget
*cfmenu
= gtk_menu_new();
94 /* Check friends on/off */
95 item
= gtk_check_menu_item_new_with_mnemonic(_("_Check friends view for new entries"));
96 gtk_menu_shell_append(GTK_MENU_SHELL(cfmenu
), item
);
97 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item
), (state
!= CF_DISABLED
));
98 g_signal_connect(G_OBJECT(item
), "activate", G_CALLBACK(cf_toggle_cb
), cff
);
99 gtk_widget_show(item
);
103 item
= gtk_separator_menu_item_new();
104 gtk_menu_shell_append(GTK_MENU_SHELL(cfmenu
), item
);
105 gtk_widget_show(item
);
109 item
= gtk_image_menu_item_new_from_stock(GTK_STOCK_PREFERENCES
, accelgroup
);
110 gtk_menu_shell_append(GTK_MENU_SHELL(cfmenu
), item
);
111 g_signal_connect_swapped(G_OBJECT(item
), "activate", G_CALLBACK(settings_cf_run
), cfm
);
112 gtk_widget_show(item
);
115 /* open friends list in browser */
116 item
= gtk_image_menu_item_new_with_mnemonic(_("_Open friends list in browser"));
117 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item
), gtk_image_new_from_stock(GTK_STOCK_JUMP_TO
, GTK_ICON_SIZE_MENU
));
118 gtk_menu_shell_append(GTK_MENU_SHELL(cfmenu
), item
);
119 g_signal_connect_swapped(G_OBJECT(item
), "activate", G_CALLBACK(open_friends_list
), cfm
);
120 gtk_widget_show_all(item
);
122 gtk_menu_popup(GTK_MENU(cfmenu
), NULL
, NULL
, NULL
, NULL
, ev
->button
, ev
->time
);
126 static gboolean
clicked_cb (GtkWidget
*w
, GdkEventButton
*ev
, CFFloat
*cff
) {
127 CFMgr
*cfm
= cff
->cfmgr
;
128 CFState state
= cfmgr_get_state(cfm
);
129 /* right-clicks start context menu (note: this case is terminal) */
130 if (ev
->button
== 3) {
131 cf_context_menu(cff
, ev
);
134 /* *all* left-clicks move CF_NEW to CF_ON */
135 if (state
== CF_NEW
) cfmgr_set_state(cfm
, CF_ON
);
136 if (ev
->button
== 2) cfmgr_set_state(cfm
, CF_NEW
); // XXX testing
137 /* and double-clicks open up the browser, too */
138 if (ev
->type
== GDK_2BUTTON_PRESS
) {
139 // XXX open_friends_list(GTK_WINDOW(cff->parent));
142 /* this help box will only be called once in a double-click,
143 * thankfully, because the above is terminal on double-clicks. */
145 if (state == CF_DISABLED) {
146 jam_message(GTK_WINDOW(cff->parent), JAM_MSG_INFO, TRUE,
147 _("Check Friends"), _(cf_help));
154 static void cf_float_state_changed_cb (CFMgr
*cfm
, CFState state
, CFFloat
*cff
) {
155 cf_float_update(cff
, state
);
156 /* autoraise if necessary */
157 if (state
== CF_NEW
&& conf
.options
.cffloatraise
) gtk_window_present(GTK_WINDOW(cff
->win
));
161 CFFloat
*cf_float_new (CFMgr
*cfm
) {
162 CFFloat
*cff
= g_new0(CFFloat
, 1);
164 g_signal_connect(G_OBJECT(cfm
), "state_changed", G_CALLBACK(cf_float_state_changed_cb
), cff
);
166 cff
->win
= gtk_window_new(GTK_WINDOW_TOPLEVEL
);
167 g_signal_connect(G_OBJECT(cff
->win
), "destroy", G_CALLBACK(cf_float_destroyed_cb
), cff
);
168 gtk_window_set_wmclass(GTK_WINDOW(cff
->win
), "logjam-checkfriends", "logjam-checkfriends");
169 geometry_tie(cff
->win
, GEOM_CFFLOAT
);
171 cff
->box
= gtk_event_box_new();
172 gtk_container_set_border_width(GTK_CONTAINER(cff
->box
), 3);
173 g_signal_connect(G_OBJECT(cff
->box
), "button_press_event", G_CALLBACK(clicked_cb
), cff
);
175 cff
->throbber
= throbber_new();
176 gtk_container_add(GTK_CONTAINER(cff
->box
), cff
->throbber
);
178 if (!conf
.options
.cffloat_decorate
) {
179 GtkWidget
*frame
= gtk_frame_new(NULL
);
180 gtk_frame_set_shadow_type(GTK_FRAME(frame
), GTK_SHADOW_OUT
);
181 gtk_container_add(GTK_CONTAINER(cff
->win
), frame
);
182 gtk_container_add(GTK_CONTAINER(frame
), cff
->box
);
183 gtk_window_set_decorated(GTK_WINDOW(cff
->win
), FALSE
);
185 gtk_container_add(GTK_CONTAINER(cff
->win
), cff
->box
);
187 cf_float_update(cff
, cfmgr_get_state(cfm
));
188 gtk_widget_show_all(cff
->win
);
194 void cf_update_dock (CFMgr
*cfm
, GtkWindow
*parent
) {
195 if (!conf
.options
.docklet
&& app
.docklet
) {
196 cf_dock_destroy(app
.docklet
);
197 } else if (conf
.options
.docklet
&& !app
.docklet
) {
198 app
.docklet
= cf_float_new(cfm
);
204 static void cf_float_destroyed_cb (GtkWidget
*widget
, CFFloat
*cff
) {
205 CFMgr
*cfm
= cff
->cfmgr
;
206 g_signal_handlers_disconnect_matched(cfm
, G_SIGNAL_MATCH_DATA
, 0, 0, NULL
, NULL
, cff
);
210 static void cf_float_destroy (CFFloat
*cff
) {
211 if (GTK_IS_WIDGET(cff
->win
)) gtk_widget_destroy(cff
->win
);
216 void cf_app_update_float (void) {
217 if (!conf
.options
.cffloat
&& app
.cf_float
) {
218 cf_float_destroy(app
.cf_float
);
220 } else if (conf
.options
.cffloat
&& !app
.cf_float
) {
221 app
.cf_float
= cf_float_new(app
.cfmgr
);
226 /* Docklet code based on docklet plugin for Gaim, copyright Robert McQueen */
228 static void cf_dock_destroy (CFFloat
*cff
) {
229 g_signal_handlers_disconnect_by_func(G_OBJECT(cff
->win
), G_CALLBACK(cf_dock_destroyed_cb
), NULL
);
230 gtk_widget_destroy(GTK_WIDGET(cff
->win
));
235 static void cf_dock_destroyed_cb(GtkWidget
*widget
, CFFloat
*cff
) {
238 #endif /* USE_DOCK */
241 void cf_float_decorate_refresh (void) {
242 /* suck a bunch of events in. */
243 while (gtk_events_pending()) gtk_main_iteration();
245 gtk_window_set_decorated(GTK_WINDOW(app
.cf_float
->win
), conf
.options
.cffloat_decorate
);
246 gtk_widget_hide(app
.cf_float
->win
);
247 gtk_widget_show(app
.cf_float
->win
);