comparison plugins/docklet/docklet.c @ 3517:6b0cb60162f4

[gaim-migrate @ 3590] Rob McQueen added a mute feature to his nice little docklet. I added a queuing feature. Configure the docklet in the plugins dialog to queue unread messages, and when you receive a message the docklet will eat it up and show a little message pending icon. Click on it, and read your message. ICQ people will like it. I also made plugin_event use a va_list. I bet this breaks perl. committer: Tailor Script <tailor@pidgin.im>
author Sean Egan <seanegan@gmail.com>
date Mon, 16 Sep 2002 08:35:24 +0000
parents b1ebeecfd2aa
children ff62b03bee6d
comparison
equal deleted inserted replaced
3516:db00eb77997d 3517:6b0cb60162f4
21 21
22 /* todo (in order of importance): 22 /* todo (in order of importance):
23 - don't crash when the plugin gets unloaded (it seems to crash after 23 - don't crash when the plugin gets unloaded (it seems to crash after
24 the plugin has gone, when gtk updates the button in the plugins 24 the plugin has gone, when gtk updates the button in the plugins
25 dialog. backtrace is always useless. weird) 25 dialog. backtrace is always useless. weird)
26 - have a toggle on the menu to mute all Gaim sounds
27 - handle and update tooltips to show your current accounts 26 - handle and update tooltips to show your current accounts
28 - connecting status support (needs more fruxing with the core)
29 - dernyi's account status menu in the right click 27 - dernyi's account status menu in the right click
30 - store icons in gtk2 stock icon thing (needs doing for the whole prog) 28 - store icons in gtk2 stock icon thing (needs doing for the whole prog)
31 - pop up notices when GNOME2's system-tray-applet supports it, with a 29 - pop up notices when GNOME2's system-tray-applet supports it, with a
32 prefs dialog to choose what to alert for */ 30 prefs dialog to choose what to alert for */
33 31
34 /* includes */ 32 /* includes */
35 #define GAIM_PLUGINS 33 #define GAIM_PLUGINS
36 #include <gtk/gtk.h> 34 #include <gtk/gtk.h>
35 #include <fcntl.h>
37 #include "gaim.h" 36 #include "gaim.h"
38 #include "eggtrayicon.h" 37 #include "eggtrayicon.h"
39
40 /* macros */
41 #define DOCKLET_WINDOW_ICONIFIED(x) (gdk_window_get_state(GTK_WIDGET(x)->window) & GDK_WINDOW_STATE_ICONIFIED)
42 38
43 /* types */ 39 /* types */
44 enum docklet_status { 40 enum docklet_status {
45 online, 41 online,
46 away, 42 away,
47 away_pending, 43 away_pending,
44 unread_pending,
48 connecting, 45 connecting,
49 offline 46 offline
50 }; 47 };
51 48
52 /* functions */ 49 /* functions */
54 51
55 /* globals */ 52 /* globals */
56 static EggTrayIcon *docklet = NULL; 53 static EggTrayIcon *docklet = NULL;
57 static GtkWidget *icon; 54 static GtkWidget *icon;
58 static enum docklet_status status; 55 static enum docklet_status status;
56 static GtkWidget *configwin = NULL;
59 57
60 static void docklet_embedded(GtkWidget *widget, void *data) { 58 static void docklet_embedded(GtkWidget *widget, void *data) {
61 debug_printf("Docklet: embedded\n"); 59 debug_printf("Docklet: embedded\n");
62 docklet_add(); 60 docklet_add();
63 } 61 }
66 debug_printf("Docklet: destroyed\n"); 64 debug_printf("Docklet: destroyed\n");
67 docklet_remove(); 65 docklet_remove();
68 docklet_create(); 66 docklet_create();
69 } 67 }
70 68
71 static void docklet_toggle() { 69
72 /* this looks bad, but we need to use (un)hide_buddy_list to allow buddy.c to 70 static void docklet_mute(GtkWidget *toggle, void *data) {
73 correctly hide/iconify depending on the docklet refcount, and to reposition 71 mute_sounds = GTK_CHECK_MENU_ITEM(toggle)->active;
74 the blist for us when we unhide. no such constraint for the login window 72 if (mute_sounds) {
75 because nothing else needs a unified way to hide/iconify it. otherwise I'd 73 debug_printf("Docklet: sounds muted\n");
76 make a function and use it for both. */ 74 } else {
77 if (connections) { 75 debug_printf("Docklet: sounds unmuted\n");
78 if (GTK_WIDGET_VISIBLE(blist)) { 76 }
79 if (DOCKLET_WINDOW_ICONIFIED(blist)) { 77 }
80 unhide_buddy_list(); 78
81 } else {
82 hide_buddy_list();
83 }
84 } else {
85 unhide_buddy_list();
86 }
87 } else {
88 if (GTK_WIDGET_VISIBLE(mainwindow)) {
89 if (DOCKLET_WINDOW_ICONIFIED(mainwindow)) {
90 gtk_window_present(GTK_WINDOW(mainwindow));
91 } else {
92 gtk_widget_hide(mainwindow);
93 }
94 } else {
95 gtk_window_present(GTK_WINDOW(mainwindow));
96 }
97 }
98 }
99 79
100 static void docklet_menu(GdkEventButton *event) { 80 static void docklet_menu(GdkEventButton *event) {
101 static GtkWidget *menu = NULL; 81 static GtkWidget *menu = NULL;
102 GtkWidget *entry; 82 GtkWidget *entry;
103 83
152 } 132 }
153 133
154 entry = gtk_separator_menu_item_new(); 134 entry = gtk_separator_menu_item_new();
155 gtk_menu_append(GTK_MENU(menu), entry); 135 gtk_menu_append(GTK_MENU(menu), entry);
156 136
137 entry = gtk_check_menu_item_new_with_label(_("Mute Sounds"));
138 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(entry), mute_sounds);
139 g_signal_connect(GTK_WIDGET(entry), "toggled", G_CALLBACK(docklet_mute), NULL);
140 gtk_menu_append(GTK_MENU(menu), entry);
141
157 entry = gtk_menu_item_new_with_label(_("Accounts")); 142 entry = gtk_menu_item_new_with_label(_("Accounts"));
158 g_signal_connect(GTK_WIDGET(entry), "activate", G_CALLBACK(account_editor), NULL); 143 g_signal_connect(GTK_WIDGET(entry), "activate", G_CALLBACK(account_editor), NULL);
159 gtk_menu_append(GTK_MENU(menu), entry); 144 gtk_menu_append(GTK_MENU(menu), entry);
160 145
161 entry = gtk_image_menu_item_new_from_stock(GTK_STOCK_PREFERENCES, NULL); 146 entry = gtk_image_menu_item_new_from_stock(GTK_STOCK_PREFERENCES, NULL);
182 } 167 }
183 168
184 static void docklet_clicked(GtkWidget *button, GdkEventButton *event, void *data) { 169 static void docklet_clicked(GtkWidget *button, GdkEventButton *event, void *data) {
185 switch (event->button) { 170 switch (event->button) {
186 case 1: 171 case 1:
187 docklet_toggle(); 172 if (unread_message_queue) {
173 purge_away_queue(unread_message_queue);
174 unread_message_queue=NULL;
175 docklet_update_status();
176 }
177 else
178 docklet_toggle();
188 break; 179 break;
189 case 2: 180 case 2:
190 break; 181 break;
191 case 3: 182 case 3:
192 docklet_menu(event); 183 docklet_menu(event);
206 filename = g_build_filename(DATADIR, "pixmaps", "gaim", "away.png", NULL); 197 filename = g_build_filename(DATADIR, "pixmaps", "gaim", "away.png", NULL);
207 break; 198 break;
208 case away_pending: 199 case away_pending:
209 filename = g_build_filename(DATADIR, "pixmaps", "gaim", "msgpend.png", NULL); 200 filename = g_build_filename(DATADIR, "pixmaps", "gaim", "msgpend.png", NULL);
210 break; 201 break;
202 case unread_pending:
203 /* XXX MAKE ME BLINK! */
204 filename = g_build_filename(DATADIR, "pixmaps", "gaim", "msgunread.png", NULL);
205 break;
211 case connecting: 206 case connecting:
212 filename = g_build_filename(DATADIR, "pixmaps", "gaim", "connecting.png", NULL); 207 filename = g_build_filename(DATADIR, "pixmaps", "gaim", "connect.png", NULL);
213 break; 208 break;
214 case offline: 209 case offline:
215 filename = g_build_filename(DATADIR, "pixmaps", "gaim", "offline.png", NULL); 210 filename = g_build_filename(DATADIR, "pixmaps", "gaim", "offline.png", NULL);
216 } 211 }
217 212
237 enum docklet_status oldstatus; 232 enum docklet_status oldstatus;
238 233
239 oldstatus = status; 234 oldstatus = status;
240 235
241 if (connections) { 236 if (connections) {
242 if (awaymessage) { 237 if (unread_message_queue) {
238 status = unread_pending;
239 } else if (awaymessage) {
243 if (message_queue) { 240 if (message_queue) {
244 status = away_pending; 241 status = away_pending;
245 } else { 242 } else {
246 status = away; 243 status = away;
247 } 244 }
248 } else { 245 } else {
249 status = online; 246 status = online;
250 } 247 }
251 } else { 248 } else {
252 status = offline; 249 if (connecting_count) {
250 status = connecting;
251 } else {
252 status = offline;
253 }
253 } 254 }
254 255
255 if (status != oldstatus) { 256 if (status != oldstatus) {
256 docklet_update_icon(); 257 docklet_update_icon();
257 } 258 }
338 gaim_signal_connect(handle, event_new_conversation, gaim_new_conversation, NULL); 339 gaim_signal_connect(handle, event_new_conversation, gaim_new_conversation, NULL);
339 340
340 return NULL; 341 return NULL;
341 } 342 }
342 343
344 static void toggle_queue (GtkWidget *w, void *null) {
345 away_options ^= OPT_AWAY_QUEUE_UNREAD;
346 save_prefs();
347 }
348
349 void gaim_plugin_config() {
350 /* This is the sorriest dialog ever written ever */
351 /* It's a good thing I plan on rewriting it later tonight */
352 GtkWidget *button;
353 GtkWidget *vbox;
354
355 if (configwin) return;
356 GAIM_DIALOG(configwin);
357
358 vbox = gtk_vbox_new(0, 6);
359 gtk_container_add(GTK_CONTAINER(configwin), vbox);
360 gtk_window_set_title(GTK_WINDOW(configwin), "Docklet Configuration");
361
362 button = gtk_check_button_new_with_mnemonic("_Hide new messages until docklet is clicked");
363 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(button), away_options & OPT_AWAY_QUEUE_UNREAD);
364 gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(toggle_queue), NULL);
365 gtk_box_pack_end(GTK_BOX(vbox), button, 0, 0, 0);
366
367 gtk_widget_show_all(configwin);
368 }
369
370
343 void gaim_plugin_remove() { 371 void gaim_plugin_remove() {
344 if (GTK_WIDGET_VISIBLE(docklet)) { 372 if (GTK_WIDGET_VISIBLE(docklet)) {
345 docklet_remove(); 373 docklet_remove();
346 } 374 }
347 375