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 }