src/mn-popup.gob (6068B) - raw
1 /*
2 * Mail Notification
3 * Copyright (C) 2003-2008 Jean-Yves Lefort <jylefort@brutele.be>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 %headertop{
21 #include <libnotify/notify.h>
22 #include "mn-message.h"
23 %}
24
25 %{
26 #include <glib/gi18n.h>
27 #include "mn-conf.h"
28 #include "mn-shell.h"
29 #include "mn-util.h"
30 %}
31
32 class MN:Popup from Notify:Notification
33 {
34 private MNMessage *message unrefwith g_object_unref;
35 property OBJECT message (flags = CONSTRUCT_ONLY, link, object_type = MN:Message, type = MNMessage *);
36
37 public gboolean visible;
38 public GTimeVal show_timestamp;
39
40 constructor (self)
41 {
42 GString *body;
43
44 body = g_string_new(NULL);
45 self_append_row(body, _("Mailbox:"), selfp->message->mailbox->runtime_name);
46 self_append_row(body, _("From:"), selfp->message->from);
47 self_append_row(body, _("Subject:"), selfp->message->subject);
48
49 g_object_set(self,
50 "body", body->str,
51 "icon-name", "stock_mail",
52 NULL);
53
54 if (mn_conf_get_enum_value(MN_TYPE_POPUP_POSITION, MN_CONF_POPUPS_POSITION) == MN_POPUP_POSITION_ATTACHED) {
55 self_wait_for_icon_to_become_ready(self);
56 g_object_set(self, "attach-widget", mn_shell->icon, NULL);
57 }
58
59 g_string_free(body, TRUE);
60
61 self_add_actions(self);
62
63 notify_notification_set_timeout(NOTIFY_NOTIFICATION(self), self_get_conf_timeout());
64
65 g_signal_connect(self, "closed", G_CALLBACK(self_closed_h), NULL);
66 }
67
68 private void wait_for_icon_to_become_ready(self) {
69 int x, y;
70 int count = 0;
71
72 /* When the tray icon is created, it can still take some time before
73 * it has arrived at the correct position. This is especially the case
74 * on KDE environments. To work around this, add a little delay of at
75 * most 2 seconds before showing a popup which is attached to the notification */
76 do {
77 gdk_window_get_origin (gtk_widget_get_window (mn_shell->icon), &x, &y);
78
79 if (x != 0 || y != 0) {
80 break;
81 }
82
83 g_usleep(G_USEC_PER_SEC / 10);
84 count++;
85 } while (count < 20);
86 }
87
88 private void
89 add_actions (self)
90 {
91 GSList *actions;
92 GSList *l;
93
94 /*
95 * Note that notification-daemon currently assigns icons to
96 * actions by prepending "stock_" to the action ID.
97 */
98
99 actions = mn_conf_get_string_list(MN_CONF_POPUPS_ACTIONS);
100
101 MN_LIST_FOREACH(l, actions)
102 {
103 char *name = l->data;
104 MNMessageAction *action;
105
106 action = mn_message_get_action(name);
107 if (action)
108 {
109 if (mn_message_can_perform_action(selfp->message, action))
110 notify_notification_add_action(NOTIFY_NOTIFICATION(self),
111 action->icon,
112 _(action->label),
113 self_action_cb,
114 action,
115 NULL);
116 }
117 else
118 g_warning(_("configuration key %s: there is no action named \"%s\""), MN_CONF_POPUPS_ACTIONS, name);
119 }
120
121 mn_g_slist_free_deep(actions);
122 }
123
124 private void
125 action_cb (NotifyNotification *notification, char *id, gpointer user_data)
126 {
127 Self *self = SELF(notification);
128 MNMessageAction *action = user_data;
129
130 GDK_THREADS_ENTER();
131
132 mn_message_perform_action(selfp->message, action, self_action_done_cb, self);
133
134 GDK_THREADS_LEAVE();
135 }
136
137 private void
138 action_done_cb (MNMessageAction *action, GError *err, gpointer data)
139 {
140 if (err && ! g_error_matches(err, MN_MESSAGE_ACTION_ERROR, MN_MESSAGE_ACTION_ERROR_CANCELLED))
141 mn_show_error_dialog(NULL, _(action->error_message), "%s", err->message);
142 }
143
144 private void
145 closed_h (NotifyNotification *notification, gpointer user_data)
146 {
147 Self *self = SELF(notification);
148 self->visible = FALSE;
149 }
150
151 private void
152 append_row (GString *body (check null),
153 const char *name (check null),
154 const char *value (check null))
155 {
156 char *escaped;
157
158 if (*body->str)
159 g_string_append_c(body, '\n');
160
161 g_string_append_printf(body, "<span weight=\"bold\">%s</span>", name);
162
163 escaped = g_markup_escape_text(value, -1);
164 g_string_append_printf(body, " %s", escaped);
165 g_free(escaped);
166 }
167
168 private int
169 get_conf_timeout (void)
170 {
171 switch (mn_conf_get_enum_value(MN_TYPE_EXPIRATION_ENABLED, MN_CONF_POPUPS_EXPIRATION_ENABLED))
172 {
173 case MN_EXPIRATION_ENABLED_DEFAULT:
174 return NOTIFY_EXPIRES_DEFAULT;
175
176 case MN_EXPIRATION_ENABLED_FALSE:
177 return NOTIFY_EXPIRES_NEVER;
178
179 case MN_EXPIRATION_ENABLED_TRUE:
180 return mn_conf_get_int(MN_CONF_POPUPS_EXPIRATION_DELAY) * 1000;
181
182 default:
183 g_assert_not_reached();
184 return 0;
185 }
186 }
187
188 public void
189 show (self)
190 {
191 GError *err = NULL;
192
193 if (self->visible)
194 return;
195
196 if (! notify_notification_show(NOTIFY_NOTIFICATION(self), &err))
197 {
198 g_warning(_("unable to show popup: %s"), err->message);
199 g_error_free(err);
200 }
201
202 self->visible = TRUE;
203 g_get_current_time(&self->show_timestamp);
204 }
205
206 public void
207 close (self)
208 {
209 GError *err = NULL;
210
211 if (! self->visible)
212 return;
213
214 if (! notify_notification_close(NOTIFY_NOTIFICATION(self), &err))
215 {
216 g_warning(_("unable to close popup: %s"), err->message);
217 g_error_free(err);
218 }
219 }
220
221 public MNPopup *
222 new (MN:Message *message (check null type))
223 {
224 /* we set the summary here because libnotify requires it */
225
226 /* translators: header capitalization */
227 return GET_NEW_VARG("summary", _("New Message"),
228 MN_POPUP_PROP_MESSAGE(message),
229 NULL);
230 }
231 }