1 /* * Copyright (C) 2009 Collabora Ltd.
3 * This library is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Lesser General Public
5 * License as published by the Free Software Foundation; either
6 * version 2.1 of the License, or (at your option) any later version.
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 * Authors: Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
21 #include "empathy-notifications-approver.h"
23 #include <glib/gi18n.h>
25 #include "empathy-call-utils.h"
26 #include "empathy-event-manager.h"
27 #include "empathy-notify-manager.h"
29 #define DEBUG_FLAG EMPATHY_DEBUG_OTHER
30 #include "empathy-debug.h"
32 struct _EmpathyNotificationsApproverPrivate
34 EmpathyEventManager
*event_mgr
;
35 EmpathyNotifyManager
*notify_mgr
;
37 NotifyNotification
*notification
;
41 G_DEFINE_TYPE (EmpathyNotificationsApprover
, empathy_notifications_approver
,
44 static EmpathyNotificationsApprover
*notifications_approver
= NULL
;
47 notifications_approver_constructor (GType type
,
48 guint n_construct_params
,
49 GObjectConstructParam
*construct_params
)
53 if (notifications_approver
!= NULL
)
54 return g_object_ref (notifications_approver
);
56 retval
= G_OBJECT_CLASS (empathy_notifications_approver_parent_class
)->
57 constructor (type
, n_construct_params
, construct_params
);
59 notifications_approver
= EMPATHY_NOTIFICATIONS_APPROVER (retval
);
60 g_object_add_weak_pointer (retval
, (gpointer
) ¬ifications_approver
);
66 notifications_approver_dispose (GObject
*object
)
68 EmpathyNotificationsApprover
*self
= (EmpathyNotificationsApprover
*) object
;
70 tp_clear_object (&self
->priv
->event_mgr
);
71 tp_clear_object (&self
->priv
->notify_mgr
);
73 if (self
->priv
->notification
!= NULL
)
75 notify_notification_close (self
->priv
->notification
, NULL
);
76 tp_clear_object (&self
->priv
->notification
);
79 G_OBJECT_CLASS (empathy_notifications_approver_parent_class
)->dispose (
84 empathy_notifications_approver_class_init (
85 EmpathyNotificationsApproverClass
*klass
)
87 GObjectClass
*object_class
= G_OBJECT_CLASS (klass
);
89 object_class
->dispose
= notifications_approver_dispose
;
90 object_class
->constructor
= notifications_approver_constructor
;
92 g_type_class_add_private (object_class
,
93 sizeof (EmpathyNotificationsApproverPrivate
));
97 notification_closed_cb (NotifyNotification
*notification
,
98 EmpathyNotificationsApprover
*self
)
100 if (self
->priv
->notification
== notification
)
101 tp_clear_object (&self
->priv
->notification
);
105 notification_close_helper (EmpathyNotificationsApprover
*self
)
107 if (self
->priv
->notification
!= NULL
)
109 notify_notification_close (self
->priv
->notification
, NULL
);
110 tp_clear_object (&self
->priv
->notification
);
115 notification_approve_no_video_cb (NotifyNotification
*notification
,
117 EmpathyNotificationsApprover
*self
)
119 if (self
->priv
->event
)
121 empathy_call_channel_send_video (
122 TP_CALL_CHANNEL (self
->priv
->event
->handler_instance
),
124 empathy_event_approve (self
->priv
->event
);
129 notification_approve_cb (NotifyNotification
*notification
,
131 EmpathyNotificationsApprover
*self
)
133 if (self
->priv
->event
!= NULL
)
134 empathy_event_approve (self
->priv
->event
);
138 notification_decline_cb (NotifyNotification
*notification
,
140 EmpathyNotificationsApprover
*self
)
142 if (self
->priv
->event
!= NULL
)
143 empathy_event_decline (self
->priv
->event
);
147 notification_decline_subscription_cb (NotifyNotification
*notification
,
149 EmpathyNotificationsApprover
*self
)
151 if (self
->priv
->event
== NULL
)
154 empathy_contact_remove_from_contact_list (self
->priv
->event
->contact
);
156 empathy_event_remove (self
->priv
->event
);
160 notification_accept_subscription_cb (NotifyNotification
*notification
,
162 EmpathyNotificationsApprover
*self
)
164 if (self
->priv
->event
== NULL
)
167 empathy_contact_add_to_contact_list (self
->priv
->event
->contact
, "");
169 empathy_event_remove (self
->priv
->event
);
173 add_notification_actions (EmpathyNotificationsApprover
*self
,
174 NotifyNotification
*notification
)
178 switch (self
->priv
->event
->type
) {
179 case EMPATHY_EVENT_TYPE_CHAT
:
180 case EMPATHY_EVENT_TYPE_MENTIONED
:
181 notify_notification_add_action (notification
,
182 "respond", _("Respond"), (NotifyActionCallback
) notification_approve_cb
,
186 case EMPATHY_EVENT_TYPE_CALL
:
187 video
= tp_call_channel_has_initial_video (
188 TP_CALL_CHANNEL (self
->priv
->event
->handler_instance
), NULL
);
190 notify_notification_add_action (notification
,
191 "reject", _("Reject"), (NotifyActionCallback
) notification_decline_cb
,
194 if (video
&& self
->priv
->event
->type
== EMPATHY_EVENT_TYPE_CALL
)
195 notify_notification_add_action (notification
,
196 "answer-no-video", _("Answer"),
197 (NotifyActionCallback
) notification_approve_no_video_cb
,
200 notify_notification_add_action (notification
,
201 "answer", video
? _("Answer with video") : _("Answer"),
202 (NotifyActionCallback
) notification_approve_cb
,
206 case EMPATHY_EVENT_TYPE_TRANSFER
:
207 case EMPATHY_EVENT_TYPE_INVITATION
:
208 notify_notification_add_action (notification
,
209 "decline", _("Decline"), (NotifyActionCallback
) notification_decline_cb
,
212 notify_notification_add_action (notification
,
213 "accept", _("Accept"), (NotifyActionCallback
) notification_approve_cb
,
217 case EMPATHY_EVENT_TYPE_SUBSCRIPTION
:
218 notify_notification_add_action (notification
,
219 "decline", _("Decline"),
220 (NotifyActionCallback
) notification_decline_subscription_cb
,
223 notify_notification_add_action (notification
,
224 "accept", _("Accept"),
225 (NotifyActionCallback
) notification_accept_subscription_cb
,
229 case EMPATHY_EVENT_TYPE_AUTH
:
230 notify_notification_add_action (notification
,
231 /* translators: the 'Provide' button is displayed in a notification
232 * bubble when Empathy is asking for an account password; clicking on it
233 * brings the password popup. */
234 "provide", _("Provide"), (NotifyActionCallback
) notification_approve_cb
,
244 notification_is_urgent (EmpathyNotificationsApprover
*self
,
245 NotifyNotification
*notification
)
247 /* Mark as urgent all the notifications with which user should
249 switch (self
->priv
->event
->type
) {
250 case EMPATHY_EVENT_TYPE_CHAT
:
251 case EMPATHY_EVENT_TYPE_CALL
:
252 case EMPATHY_EVENT_TYPE_TRANSFER
:
253 case EMPATHY_EVENT_TYPE_INVITATION
:
254 case EMPATHY_EVENT_TYPE_AUTH
:
255 case EMPATHY_EVENT_TYPE_MENTIONED
:
258 case EMPATHY_EVENT_TYPE_SUBSCRIPTION
:
259 case EMPATHY_EVENT_TYPE_PRESENCE_ONLINE
:
260 case EMPATHY_EVENT_TYPE_PRESENCE_OFFLINE
:
268 get_category_for_event_type (EmpathyEventType type
)
271 case EMPATHY_EVENT_TYPE_##x: \
272 return EMPATHY_NOTIFICATION_CATEGORY_##x;
275 CASE(PRESENCE_ONLINE
)
276 CASE(PRESENCE_OFFLINE
)
290 update_notification (EmpathyNotificationsApprover
*self
)
292 GdkPixbuf
*pixbuf
= NULL
;
293 gchar
*message_esc
= NULL
;
294 gboolean has_x_canonical_append
;
295 NotifyNotification
*notification
;
297 if (!empathy_notify_manager_notification_is_enabled (self
->priv
->notify_mgr
))
299 /* always close the notification if this happens */
300 notification_close_helper (self
);
304 if (self
->priv
->event
== NULL
)
306 notification_close_helper (self
);
310 if (self
->priv
->event
->message
!= NULL
)
311 message_esc
= g_markup_escape_text (self
->priv
->event
->message
, -1);
313 has_x_canonical_append
= empathy_notify_manager_has_capability (
314 self
->priv
->notify_mgr
, EMPATHY_NOTIFY_MANAGER_CAP_X_CANONICAL_APPEND
);
316 if (self
->priv
->notification
!= NULL
&& ! has_x_canonical_append
)
318 /* if the notification server does NOT supports x-canonical-append, it is
319 * better to not use notify_notification_update to avoid
320 * overwriting the current notification message */
321 notification
= g_object_ref (self
->priv
->notification
);
323 notify_notification_update (notification
,
324 self
->priv
->event
->header
, message_esc
, NULL
);
328 const gchar
*category
;
330 /* if the notification server supports x-canonical-append,
331 * the hint will be added, so that the message from the
332 * just created notification will be automatically appended
333 * to an existing notification with the same title.
334 * In this way the previous message will not be lost: the new
335 * message will appear below it, in the same notification */
336 notification
= empathy_notify_manager_create_notification (
337 self
->priv
->event
->header
, message_esc
, NULL
);
339 if (self
->priv
->notification
== NULL
)
341 self
->priv
->notification
= g_object_ref (notification
);
343 g_signal_connect (notification
, "closed",
344 G_CALLBACK (notification_closed_cb
), self
);
347 if (has_x_canonical_append
)
349 notify_notification_set_hint (notification
,
350 EMPATHY_NOTIFY_MANAGER_CAP_X_CANONICAL_APPEND
,
351 g_variant_new_boolean (TRUE
));
354 if (empathy_notify_manager_has_capability (self
->priv
->notify_mgr
,
355 EMPATHY_NOTIFY_MANAGER_CAP_ACTIONS
))
356 add_notification_actions (self
, notification
);
358 if (notification_is_urgent (self
, notification
))
359 notify_notification_set_urgency (notification
, NOTIFY_URGENCY_CRITICAL
);
361 category
= get_category_for_event_type (self
->priv
->event
->type
);
362 if (category
!= NULL
)
364 notify_notification_set_hint (notification
,
365 EMPATHY_NOTIFY_MANAGER_CAP_CATEGORY
,
366 g_variant_new_string (category
));
370 pixbuf
= empathy_notify_manager_get_pixbuf_for_notification (
371 self
->priv
->notify_mgr
, self
->priv
->event
->contact
,
372 self
->priv
->event
->icon_name
);
376 notify_notification_set_image_from_pixbuf (notification
, pixbuf
);
377 g_object_unref (pixbuf
);
380 notify_notification_show (notification
, NULL
);
382 g_free (message_esc
);
383 g_object_unref (notification
);
387 event_added_cb (EmpathyEventManager
*manager
,
389 EmpathyNotificationsApprover
*self
)
391 if (self
->priv
->event
!= NULL
)
394 self
->priv
->event
= event
;
396 update_notification (self
);
400 event_removed_cb (EmpathyEventManager
*manager
,
402 EmpathyNotificationsApprover
*self
)
404 if (event
!= self
->priv
->event
)
407 self
->priv
->event
= empathy_event_manager_get_top_event (
408 self
->priv
->event_mgr
);
410 update_notification (self
);
414 event_updated_cb (EmpathyEventManager
*manager
,
416 EmpathyNotificationsApprover
*self
)
418 if (event
!= self
->priv
->event
)
421 if (empathy_notify_manager_notification_is_enabled (self
->priv
->notify_mgr
))
422 update_notification (self
);
426 empathy_notifications_approver_init (EmpathyNotificationsApprover
*self
)
428 EmpathyNotificationsApproverPrivate
*priv
= G_TYPE_INSTANCE_GET_PRIVATE (self
,
429 EMPATHY_TYPE_NOTIFICATIONS_APPROVER
, EmpathyNotificationsApproverPrivate
);
433 self
->priv
->event_mgr
= empathy_event_manager_dup_singleton ();
434 self
->priv
->notify_mgr
= empathy_notify_manager_dup_singleton ();
436 tp_g_signal_connect_object (self
->priv
->event_mgr
, "event-added",
437 G_CALLBACK (event_added_cb
), self
, 0);
438 tp_g_signal_connect_object (priv
->event_mgr
, "event-removed",
439 G_CALLBACK (event_removed_cb
), self
, 0);
440 tp_g_signal_connect_object (priv
->event_mgr
, "event-updated",
441 G_CALLBACK (event_updated_cb
), self
, 0);
444 EmpathyNotificationsApprover
*
445 empathy_notifications_approver_dup_singleton (void)
447 return g_object_new (EMPATHY_TYPE_NOTIFICATIONS_APPROVER
, NULL
);