| 1 /* |
|
| 2 * Finch - Universal Text Chat Client |
|
| 3 * Copyright (C) Pidgin Developers <devel@pidgin.im> |
|
| 4 * |
|
| 5 * Finch is the legal property of its developers, whose names are too numerous |
|
| 6 * to list here. Please refer to the COPYRIGHT file distributed with this |
|
| 7 * source distribution. |
|
| 8 * |
|
| 9 * This program is free software; you can redistribute it and/or modify |
|
| 10 * it under the terms of the GNU General Public License as published by |
|
| 11 * the Free Software Foundation; either version 2 of the License, or |
|
| 12 * (at your option) any later version. |
|
| 13 * |
|
| 14 * This program is distributed in the hope that it will be useful, |
|
| 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 17 * GNU General Public License for more details. |
|
| 18 * |
|
| 19 * You should have received a copy of the GNU General Public License |
|
| 20 * along with this program; if not, see <https://www.gnu.org/licenses/>. |
|
| 21 */ |
|
| 22 |
|
| 23 #include <purpleconfig.h> |
|
| 24 |
|
| 25 #include <glib.h> |
|
| 26 #include <glib/gi18n-lib.h> |
|
| 27 #include <glib/gstdio.h> |
|
| 28 |
|
| 29 #include <purple.h> |
|
| 30 |
|
| 31 #include <gnt.h> |
|
| 32 |
|
| 33 #include "finchnotifications.h" |
|
| 34 |
|
| 35 #include "gntaccount.h" |
|
| 36 |
|
| 37 static struct { |
|
| 38 GntWidget *window; |
|
| 39 GntWidget *list; |
|
| 40 } notifications; |
|
| 41 |
|
| 42 /******************************************************************************* |
|
| 43 * Helpers |
|
| 44 ******************************************************************************/ |
|
| 45 static void |
|
| 46 finch_notifications_update(GntTree *list, GListModel *model) { |
|
| 47 guint index = 0; |
|
| 48 |
|
| 49 gnt_tree_remove_all(GNT_TREE(list)); |
|
| 50 |
|
| 51 for(index = 0; index < g_list_model_get_n_items(model); index++) { |
|
| 52 PurpleNotification *notification = g_list_model_get_item(model, index); |
|
| 53 GntTreeRow *row = NULL; |
|
| 54 |
|
| 55 row = gnt_tree_create_row(list, |
|
| 56 purple_notification_get_title(notification)); |
|
| 57 gnt_tree_add_row_last(list, notification, row, NULL); |
|
| 58 } |
|
| 59 } |
|
| 60 |
|
| 61 static void |
|
| 62 finch_notification_delete_notification(PurpleNotification *notification) { |
|
| 63 if(PURPLE_IS_NOTIFICATION(notification)) { |
|
| 64 PurpleNotificationManager *manager = NULL; |
|
| 65 |
|
| 66 purple_notification_delete(notification); |
|
| 67 |
|
| 68 manager = purple_notification_manager_get_default(); |
|
| 69 purple_notification_manager_remove(manager, notification); |
|
| 70 } |
|
| 71 } |
|
| 72 |
|
| 73 /******************************************************************************* |
|
| 74 * Finch Notification Callbacks |
|
| 75 ******************************************************************************/ |
|
| 76 static void |
|
| 77 finch_notification_delete(G_GNUC_UNUSED GntWidget *widget, gpointer data) { |
|
| 78 PurpleNotification *notification = g_object_get_data(data, "notification"); |
|
| 79 |
|
| 80 finch_notification_delete_notification(notification); |
|
| 81 |
|
| 82 gnt_widget_destroy(GNT_WIDGET(data)); |
|
| 83 } |
|
| 84 |
|
| 85 static void |
|
| 86 finch_notification_reconnect_account(G_GNUC_UNUSED GntWidget *widget, |
|
| 87 gpointer data) |
|
| 88 { |
|
| 89 PurpleNotification *notification = g_object_get_data(data, "notification"); |
|
| 90 PurpleAccount *account = purple_notification_get_account(notification); |
|
| 91 |
|
| 92 if(PURPLE_IS_ACCOUNT(account)) { |
|
| 93 purple_account_connect(account); |
|
| 94 } |
|
| 95 |
|
| 96 gnt_widget_destroy(GNT_WIDGET(data)); |
|
| 97 } |
|
| 98 |
|
| 99 static void |
|
| 100 finch_notification_reenable_account(G_GNUC_UNUSED GntWidget *widget, |
|
| 101 gpointer data) |
|
| 102 { |
|
| 103 PurpleNotification *notification = g_object_get_data(data, "notification"); |
|
| 104 PurpleAccount *account = purple_notification_get_account(notification); |
|
| 105 |
|
| 106 if(PURPLE_IS_ACCOUNT(account)) { |
|
| 107 purple_account_set_enabled(account, TRUE); |
|
| 108 } |
|
| 109 |
|
| 110 gnt_widget_destroy(GNT_WIDGET(data)); |
|
| 111 } |
|
| 112 |
|
| 113 static void |
|
| 114 finch_notification_modify_account(G_GNUC_UNUSED GntWidget *widget, |
|
| 115 gpointer data) |
|
| 116 { |
|
| 117 PurpleNotification *notification = g_object_get_data(data, "notification"); |
|
| 118 PurpleAccount *account = purple_notification_get_account(notification); |
|
| 119 |
|
| 120 if(PURPLE_IS_ACCOUNT(account)) { |
|
| 121 finch_account_dialog_show(account); |
|
| 122 } |
|
| 123 |
|
| 124 gnt_widget_destroy(GNT_WIDGET(data)); |
|
| 125 } |
|
| 126 |
|
| 127 static void |
|
| 128 finch_notification_contact_authorize(G_GNUC_UNUSED GntWidget *widget, |
|
| 129 gpointer data) |
|
| 130 { |
|
| 131 PurpleAccount *account = NULL; |
|
| 132 PurpleNotification *notification = NULL; |
|
| 133 PurpleNotificationManager *manager = NULL; |
|
| 134 PurpleAuthorizationRequest *auth_request = NULL; |
|
| 135 const gchar *alias = NULL, *username = NULL; |
|
| 136 |
|
| 137 /* Get the notification and authorization request from the data. */ |
|
| 138 notification = g_object_get_data(data, "notification"); |
|
| 139 auth_request = purple_notification_get_data(notification); |
|
| 140 |
|
| 141 /* Accept the authorization request. */ |
|
| 142 purple_authorization_request_accept(auth_request); |
|
| 143 |
|
| 144 /* Remove the notification from the manager. */ |
|
| 145 manager = purple_notification_manager_get_default(); |
|
| 146 purple_notification_manager_remove(manager, notification); |
|
| 147 |
|
| 148 /* Request the user to add the person they just authorized. */ |
|
| 149 account = purple_authorization_request_get_account(auth_request); |
|
| 150 alias = purple_authorization_request_get_alias(auth_request); |
|
| 151 username = purple_authorization_request_get_username(auth_request); |
|
| 152 purple_blist_request_add_buddy(account, username, NULL, alias); |
|
| 153 |
|
| 154 /* Destroy the dialog. */ |
|
| 155 gnt_widget_destroy(GNT_WIDGET(data)); |
|
| 156 } |
|
| 157 |
|
| 158 static void |
|
| 159 finch_notification_contact_deny(G_GNUC_UNUSED GntWidget *widget, gpointer data) |
|
| 160 { |
|
| 161 PurpleNotification *notification = NULL; |
|
| 162 PurpleNotificationManager *manager = NULL; |
|
| 163 PurpleAuthorizationRequest *auth_request = NULL; |
|
| 164 |
|
| 165 /* Get the notification and authorization request from the data. */ |
|
| 166 notification = g_object_get_data(data, "notification"); |
|
| 167 auth_request = purple_notification_get_data(notification); |
|
| 168 |
|
| 169 /* Deny the request. */ |
|
| 170 purple_authorization_request_deny(auth_request, NULL); |
|
| 171 |
|
| 172 /* Remove the notification from the manager. */ |
|
| 173 manager = purple_notification_manager_get_default(); |
|
| 174 purple_notification_manager_remove(manager, notification); |
|
| 175 |
|
| 176 /* Destroy the dialog. */ |
|
| 177 gnt_widget_destroy(GNT_WIDGET(data)); |
|
| 178 } |
|
| 179 |
|
| 180 /******************************************************************************* |
|
| 181 * Finch Notification API |
|
| 182 ******************************************************************************/ |
|
| 183 static void |
|
| 184 finch_notification_show(PurpleNotification *notification) { |
|
| 185 GntWidget *dialog = NULL, *label = NULL, *hbox = NULL, *button = NULL; |
|
| 186 PurpleAccount *account = NULL; |
|
| 187 PurpleNotificationType type; |
|
| 188 gpointer data = NULL; |
|
| 189 |
|
| 190 account = purple_notification_get_account(notification); |
|
| 191 |
|
| 192 dialog = gnt_box_new(FALSE, TRUE); |
|
| 193 gnt_box_set_toplevel(GNT_BOX(dialog), TRUE); |
|
| 194 gnt_box_set_alignment(GNT_BOX(dialog), GNT_ALIGN_MID); |
|
| 195 g_object_set_data(G_OBJECT(dialog), "notification", notification); |
|
| 196 |
|
| 197 label = gnt_label_new(purple_notification_get_title(notification)); |
|
| 198 gnt_box_add_widget(GNT_BOX(dialog), label); |
|
| 199 |
|
| 200 hbox = gnt_box_new(FALSE, FALSE); |
|
| 201 |
|
| 202 type = purple_notification_get_notification_type(notification); |
|
| 203 data = purple_notification_get_data(notification); |
|
| 204 |
|
| 205 if(type == PURPLE_NOTIFICATION_TYPE_GENERIC) { |
|
| 206 gnt_box_set_title(GNT_BOX(dialog), |
|
| 207 purple_notification_get_title(notification)); |
|
| 208 label = gnt_label_new(purple_notification_get_data(notification)); |
|
| 209 gnt_box_add_widget(GNT_BOX(dialog), label); |
|
| 210 } else if(type == PURPLE_NOTIFICATION_TYPE_CONNECTION_ERROR) { |
|
| 211 PurpleConnectionErrorInfo *info = data; |
|
| 212 |
|
| 213 /* Set the title. */ |
|
| 214 gnt_box_set_title(GNT_BOX(dialog), _("Connection Error")); |
|
| 215 |
|
| 216 /* Add the connection error reason. */ |
|
| 217 label = gnt_label_new(info->description); |
|
| 218 gnt_box_add_widget(GNT_BOX(dialog), label); |
|
| 219 |
|
| 220 /* Add the buttons. */ |
|
| 221 if(purple_account_get_enabled(account)) { |
|
| 222 button = gnt_button_new(_("Reconnect")); |
|
| 223 g_signal_connect(button, "activate", |
|
| 224 G_CALLBACK(finch_notification_reconnect_account), |
|
| 225 dialog); |
|
| 226 } else { |
|
| 227 button = gnt_button_new(_("Re-enable")); |
|
| 228 g_signal_connect(button, "activate", |
|
| 229 G_CALLBACK(finch_notification_reenable_account), |
|
| 230 dialog); |
|
| 231 } |
|
| 232 gnt_box_add_widget(GNT_BOX(hbox), button); |
|
| 233 |
|
| 234 button = gnt_button_new(_("Modify Account")); |
|
| 235 g_signal_connect(button, "activate", |
|
| 236 G_CALLBACK(finch_notification_modify_account), |
|
| 237 dialog); |
|
| 238 gnt_box_add_widget(GNT_BOX(hbox), button); |
|
| 239 } else if(type == PURPLE_NOTIFICATION_TYPE_AUTHORIZATION_REQUEST) { |
|
| 240 PurpleAuthorizationRequest *auth_request = NULL; |
|
| 241 const gchar *message = NULL; |
|
| 242 |
|
| 243 /* Set the title. */ |
|
| 244 gnt_box_set_title(GNT_BOX(dialog), _("Authorization Request")); |
|
| 245 |
|
| 246 auth_request = purple_notification_get_data(notification); |
|
| 247 message = purple_authorization_request_get_message(auth_request); |
|
| 248 |
|
| 249 /* Add the message if we have one. */ |
|
| 250 if(message != NULL && *message != '\0') { |
|
| 251 label = gnt_label_new(message); |
|
| 252 gnt_box_add_widget(GNT_BOX(dialog), label); |
|
| 253 } |
|
| 254 |
|
| 255 /* Add the buttons. */ |
|
| 256 button = gnt_button_new(_("Authorize")); |
|
| 257 g_signal_connect(button, "activate", |
|
| 258 G_CALLBACK(finch_notification_contact_authorize), |
|
| 259 dialog); |
|
| 260 gnt_box_add_widget(GNT_BOX(hbox), button); |
|
| 261 |
|
| 262 button = gnt_button_new(_("Deny")); |
|
| 263 g_signal_connect(button, "activate", |
|
| 264 G_CALLBACK(finch_notification_contact_deny), dialog); |
|
| 265 gnt_box_add_widget(GNT_BOX(hbox), button); |
|
| 266 } |
|
| 267 |
|
| 268 gnt_box_add_widget(GNT_BOX(dialog), hbox); |
|
| 269 |
|
| 270 button = gnt_button_new(_("Delete")); |
|
| 271 g_signal_connect(button, "activate", |
|
| 272 G_CALLBACK(finch_notification_delete), dialog); |
|
| 273 gnt_box_add_widget(GNT_BOX(hbox), button); |
|
| 274 |
|
| 275 gnt_widget_show(dialog); |
|
| 276 } |
|
| 277 |
|
| 278 /******************************************************************************* |
|
| 279 * Callbacks |
|
| 280 ******************************************************************************/ |
|
| 281 static void |
|
| 282 finch_notifications_changed_cb(GListModel *model, |
|
| 283 G_GNUC_UNUSED guint position, |
|
| 284 G_GNUC_UNUSED guint removed, |
|
| 285 guint added, |
|
| 286 gpointer data) |
|
| 287 { |
|
| 288 finch_notifications_update(data, model); |
|
| 289 |
|
| 290 if(added > 0) { |
|
| 291 gnt_widget_set_urgent(notifications.window); |
|
| 292 } |
|
| 293 } |
|
| 294 |
|
| 295 static void |
|
| 296 finch_notifications_open_cb(G_GNUC_UNUSED GntWidget *w, |
|
| 297 G_GNUC_UNUSED gpointer data) |
|
| 298 { |
|
| 299 PurpleNotification *notification = NULL; |
|
| 300 |
|
| 301 notification = gnt_tree_get_selection_data(GNT_TREE(notifications.list)); |
|
| 302 if(!PURPLE_IS_NOTIFICATION(notification)) { |
|
| 303 return; |
|
| 304 } |
|
| 305 |
|
| 306 finch_notification_show(notification); |
|
| 307 } |
|
| 308 |
|
| 309 static void |
|
| 310 finch_notifications_delete_cb(G_GNUC_UNUSED GntWidget *widget, |
|
| 311 G_GNUC_UNUSED gpointer data) |
|
| 312 { |
|
| 313 PurpleNotification *notification = NULL; |
|
| 314 |
|
| 315 notification = gnt_tree_get_selection_data(GNT_TREE(notifications.list)); |
|
| 316 |
|
| 317 finch_notification_delete_notification(notification); |
|
| 318 } |
|
| 319 |
|
| 320 |
|
| 321 static void |
|
| 322 finch_notifications_activate_cb(G_GNUC_UNUSED GntWidget *w, |
|
| 323 G_GNUC_UNUSED gpointer data) |
|
| 324 { |
|
| 325 PurpleNotification *notification = NULL; |
|
| 326 |
|
| 327 notification = gnt_tree_get_selection_data(GNT_TREE(notifications.list)); |
|
| 328 |
|
| 329 finch_notification_show(notification); |
|
| 330 } |
|
| 331 |
|
| 332 /******************************************************************************* |
|
| 333 * Public API |
|
| 334 ******************************************************************************/ |
|
| 335 void |
|
| 336 finch_notifications_window_show(void) { |
|
| 337 GntWidget *wid, *box; |
|
| 338 GListModel *model = NULL; |
|
| 339 |
|
| 340 if(notifications.window) { |
|
| 341 gnt_window_present(notifications.window); |
|
| 342 |
|
| 343 return; |
|
| 344 } |
|
| 345 |
|
| 346 notifications.window = gnt_vbox_new(FALSE); |
|
| 347 gnt_box_set_toplevel(GNT_BOX(notifications.window), TRUE); |
|
| 348 gnt_box_set_fill(GNT_BOX(notifications.window), TRUE); |
|
| 349 gnt_box_set_title(GNT_BOX(notifications.window), _("Notifications")); |
|
| 350 gnt_box_set_alignment(GNT_BOX(notifications.window), GNT_ALIGN_MID); |
|
| 351 gnt_box_set_pad(GNT_BOX(notifications.window), 0); |
|
| 352 gnt_widget_set_name(notifications.window, "notifications"); |
|
| 353 |
|
| 354 /* Create the box that lists all of the notifications. */ |
|
| 355 notifications.list = gnt_tree_new_with_columns(1); |
|
| 356 gnt_tree_set_compare_func(GNT_TREE(notifications.list), |
|
| 357 purple_notification_compare); |
|
| 358 gnt_widget_set_has_border(notifications.list, FALSE); |
|
| 359 gnt_box_add_widget(GNT_BOX(notifications.window), notifications.list); |
|
| 360 g_signal_connect(notifications.list, "activate", |
|
| 361 G_CALLBACK(finch_notifications_activate_cb), NULL); |
|
| 362 |
|
| 363 /* Get the notification manager to get the model and populate the list. */ |
|
| 364 model = purple_notification_manager_get_default_as_model(); |
|
| 365 finch_notifications_update(GNT_TREE(notifications.list), model); |
|
| 366 g_signal_connect_object(model, "items-changed", |
|
| 367 G_CALLBACK(finch_notifications_changed_cb), |
|
| 368 notifications.list, 0); |
|
| 369 |
|
| 370 gnt_box_add_widget(GNT_BOX(notifications.window), gnt_line_new(FALSE)); |
|
| 371 |
|
| 372 box = gnt_hbox_new(FALSE); |
|
| 373 gnt_box_set_alignment(GNT_BOX(box), GNT_ALIGN_MID); |
|
| 374 gnt_box_set_fill(GNT_BOX(box), FALSE); |
|
| 375 |
|
| 376 wid = gnt_button_new(_("Open")); |
|
| 377 g_signal_connect(wid, "activate", G_CALLBACK(finch_notifications_open_cb), |
|
| 378 NULL); |
|
| 379 gnt_box_add_widget(GNT_BOX(box), wid); |
|
| 380 |
|
| 381 wid = gnt_button_new(_("Delete")); |
|
| 382 g_signal_connect(wid, "activate", G_CALLBACK(finch_notifications_delete_cb), |
|
| 383 NULL); |
|
| 384 gnt_box_add_widget(GNT_BOX(box), wid); |
|
| 385 |
|
| 386 gnt_box_add_widget(GNT_BOX(notifications.window), box); |
|
| 387 |
|
| 388 gnt_widget_show(notifications.window); |
|
| 389 } |
|
| 390 |
|
| 391 void |
|
| 392 finch_notifications_init(void) { |
|
| 393 } |
|
| 394 |
|
| 395 void |
|
| 396 finch_notifications_uninit(void) { |
|
| 397 g_clear_pointer(¬ifications.window, gnt_widget_destroy); |
|
| 398 } |
|