Fri, 04 Oct 2024 01:09:26 -0500
Remove the Purple.Signals API
This was a long time coming but we've finally replaced it all!
Testing Done:
Connected a demo and irc accounts without issues. Also called in the turtles.
Reviewed at https://reviews.imfreedom.org/r/3568/
/* * Purple - Internet Messaging Library * Copyright (C) Pidgin Developers <devel@pidgin.im> * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this * source distribution. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this library; if not, see <https://www.gnu.org/licenses/>. */ #include <glib/gi18n-lib.h> #include <birb.h> #include "purplenotification.h" #include "purpleenums.h" #include "purplenotificationaddcontact.h" #include "purplenotificationauthorizationrequest.h" #include "purplenotificationconnectionerror.h" #include "util.h" typedef struct { char *id; PurpleAccount *account; GDateTime *created_timestamp; char *title; char *subtitle; char *icon_name; gboolean read; gboolean interactive; gboolean persistent; gpointer data; GDestroyNotify data_destroy_func; gboolean deleted; } PurpleNotificationPrivate; enum { SIG_DELETED, N_SIGNALS, }; static guint signals[N_SIGNALS] = {0, }; enum { PROP_0, PROP_ID, PROP_ACCOUNT, PROP_CREATED_TIMESTAMP, PROP_TITLE, PROP_SUBTITLE, PROP_ICON_NAME, PROP_READ, PROP_INTERACTIVE, PROP_PERSISTENT, N_PROPERTIES, }; static GParamSpec *properties[N_PROPERTIES] = {NULL, }; G_DEFINE_TYPE_WITH_PRIVATE(PurpleNotification, purple_notification, G_TYPE_OBJECT) /****************************************************************************** * Helpers *****************************************************************************/ static void purple_notification_set_id(PurpleNotification *notification, const char *id) { PurpleNotificationPrivate *priv = NULL; g_return_if_fail(PURPLE_IS_NOTIFICATION(notification)); priv = purple_notification_get_instance_private(notification); if(id == NULL) { priv->id = g_uuid_string_random(); } else { priv->id = g_strdup(id); } g_object_notify_by_pspec(G_OBJECT(notification), properties[PROP_ID]); } /****************************************************************************** * GObject Implementation *****************************************************************************/ static void purple_notification_get_property(GObject *obj, guint param_id, GValue *value, GParamSpec *pspec) { PurpleNotification *notification = PURPLE_NOTIFICATION(obj); switch(param_id) { case PROP_ID: g_value_set_string(value, purple_notification_get_id(notification)); break; case PROP_ACCOUNT: g_value_set_object(value, purple_notification_get_account(notification)); break; case PROP_CREATED_TIMESTAMP: g_value_set_boxed(value, purple_notification_get_created_timestamp(notification)); break; case PROP_TITLE: g_value_set_string(value, purple_notification_get_title(notification)); break; case PROP_SUBTITLE: g_value_set_string(value, purple_notification_get_subtitle(notification)); break; case PROP_ICON_NAME: g_value_set_string(value, purple_notification_get_icon_name(notification)); break; case PROP_READ: g_value_set_boolean(value, purple_notification_get_read(notification)); break; case PROP_INTERACTIVE: g_value_set_boolean(value, purple_notification_get_interactive(notification)); break; case PROP_PERSISTENT: g_value_set_boolean(value, purple_notification_get_persistent(notification)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); break; } } static void purple_notification_set_property(GObject *obj, guint param_id, const GValue *value, GParamSpec *pspec) { PurpleNotification *notification = PURPLE_NOTIFICATION(obj); switch(param_id) { case PROP_ID: purple_notification_set_id(notification, g_value_get_string(value)); break; case PROP_ACCOUNT: purple_notification_set_account(notification, g_value_get_object(value)); break; case PROP_CREATED_TIMESTAMP: purple_notification_set_created_timestamp(notification, g_value_get_boxed(value)); break; case PROP_TITLE: purple_notification_set_title(notification, g_value_get_string(value)); break; case PROP_SUBTITLE: purple_notification_set_subtitle(notification, g_value_get_string(value)); break; case PROP_ICON_NAME: purple_notification_set_icon_name(notification, g_value_get_string(value)); break; case PROP_READ: purple_notification_set_read(notification, g_value_get_boolean(value)); break; case PROP_INTERACTIVE: purple_notification_set_interactive(notification, g_value_get_boolean(value)); break; case PROP_PERSISTENT: purple_notification_set_persistent(notification, g_value_get_boolean(value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); break; } } static void purple_notification_finalize(GObject *obj) { PurpleNotification *notification = PURPLE_NOTIFICATION(obj); PurpleNotificationPrivate *priv = NULL; priv = purple_notification_get_instance_private(notification); g_clear_pointer(&priv->id, g_free); g_clear_object(&priv->account); birb_date_time_clear(&priv->created_timestamp); g_clear_pointer(&priv->title, g_free); g_clear_pointer(&priv->subtitle, g_free); g_clear_pointer(&priv->icon_name, g_free); G_OBJECT_CLASS(purple_notification_parent_class)->finalize(obj); } static void purple_notification_init(G_GNUC_UNUSED PurpleNotification *notification) { } static void purple_notification_class_init(PurpleNotificationClass *klass) { GObjectClass *obj_class = G_OBJECT_CLASS(klass); obj_class->get_property = purple_notification_get_property; obj_class->set_property = purple_notification_set_property; obj_class->finalize = purple_notification_finalize; /** * PurpleNotification:id: * * The ID of the notification. * * This used for things that need to address it. * * If not set, this will be auto populated at creation time. * * Since: 3.0 */ properties[PROP_ID] = g_param_spec_string( "id", NULL, NULL, NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); /** * PurpleNotification:account: * * An optional [class@Account] that this notification is for. * * Since: 3.0 */ properties[PROP_ACCOUNT] = g_param_spec_object( "account", NULL, NULL, PURPLE_TYPE_ACCOUNT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); /** * PurpleNotification:created-timestamp: * * The creation time of this notification. This always represented as UTC * internally, and will be set to UTC now by default. * * Since: 3.0 */ properties[PROP_CREATED_TIMESTAMP] = g_param_spec_boxed( "created-timestamp", NULL, NULL, G_TYPE_DATE_TIME, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); /** * PurpleNotification:title: * * An optional title for this notification. A user interface may or may not * choose to use this when displaying the notification. Regardless, this * should be a translated string. * * Since: 3.0 */ properties[PROP_TITLE] = g_param_spec_string( "title", NULL, NULL, NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); /** * PurpleNotification:subtitle: * * An optional subtitle for this notification. A user interface may or may * not choose to use this when displaying the notification. Regardless, * this should be a translated string. * * Since: 3.0 */ properties[PROP_SUBTITLE] = g_param_spec_string( "subtitle", NULL, NULL, NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); /** * PurpleNotification:icon-name: * * The icon-name in the icon theme to use for the notification. A user * interface may or may not choose to use this when display the * notification. * * Since: 3.0 */ properties[PROP_ICON_NAME] = g_param_spec_string( "icon-name", NULL, NULL, NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); /** * PurpleNotification:read: * * Whether or not the notification has been read. * * Since: 3.0 */ properties[PROP_READ] = g_param_spec_boolean( "read", NULL, NULL, FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); /** * PurpleNotification:interactive: * * Whether or not the notification can be interacted with. * * Since: 3.0 */ properties[PROP_INTERACTIVE] = g_param_spec_boolean( "interactive", NULL, NULL, FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); /** * PurpleNotification:persistent: * * Whether or not the notification can be dismissed by users. * * Since: 3.0 */ properties[PROP_PERSISTENT] = g_param_spec_boolean( "persistent", NULL, NULL, FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_properties(obj_class, N_PROPERTIES, properties); /** * PurpleNotification::deleted: * @notification: The instance. * * Emitted when the notification is deleted. This is typically done by a * user interface calling [method@PurpleNotification.delete]. * * Since: 3.0 */ signals[SIG_DELETED] = g_signal_new_class_handler( "deleted", G_OBJECT_CLASS_TYPE(klass), G_SIGNAL_RUN_LAST, NULL, NULL, NULL, NULL, G_TYPE_NONE, 0); } /****************************************************************************** * Public API *****************************************************************************/ PurpleNotification * purple_notification_new(const char *id, const char *title) { return g_object_new(PURPLE_TYPE_NOTIFICATION, "id", id, "title", title, NULL); } const char * purple_notification_get_id(PurpleNotification *notification) { PurpleNotificationPrivate *priv = NULL; g_return_val_if_fail(PURPLE_IS_NOTIFICATION(notification), NULL); priv = purple_notification_get_instance_private(notification); return priv->id; } PurpleAccount * purple_notification_get_account(PurpleNotification *notification) { PurpleNotificationPrivate *priv = NULL; g_return_val_if_fail(PURPLE_IS_NOTIFICATION(notification), NULL); priv = purple_notification_get_instance_private(notification); return priv->account; } void purple_notification_set_account(PurpleNotification *notification, PurpleAccount *account) { PurpleNotificationPrivate *priv = NULL; g_return_if_fail(PURPLE_IS_NOTIFICATION(notification)); priv = purple_notification_get_instance_private(notification); if(g_set_object(&priv->account, account)) { g_object_notify_by_pspec(G_OBJECT(notification), properties[PROP_ACCOUNT]); } } GDateTime * purple_notification_get_created_timestamp(PurpleNotification *notification) { PurpleNotificationPrivate *priv = NULL; g_return_val_if_fail(PURPLE_IS_NOTIFICATION(notification), NULL); priv = purple_notification_get_instance_private(notification); return priv->created_timestamp; } void purple_notification_set_created_timestamp(PurpleNotification *notification, GDateTime *timestamp) { PurpleNotificationPrivate *priv = NULL; g_return_if_fail(PURPLE_IS_NOTIFICATION(notification)); priv = purple_notification_get_instance_private(notification); if(birb_date_time_set(&priv->created_timestamp, timestamp)) { g_object_notify_by_pspec(G_OBJECT(notification), properties[PROP_CREATED_TIMESTAMP]); } } void purple_notification_set_created_timestamp_now(PurpleNotification *notification) { GDateTime *timestamp = NULL; g_return_if_fail(PURPLE_IS_NOTIFICATION(notification)); timestamp = g_date_time_new_now_local(); purple_notification_set_created_timestamp(notification, timestamp); g_date_time_unref(timestamp); } const char * purple_notification_get_title(PurpleNotification *notification) { PurpleNotificationPrivate *priv = NULL; g_return_val_if_fail(PURPLE_IS_NOTIFICATION(notification), NULL); priv = purple_notification_get_instance_private(notification); return priv->title; } void purple_notification_set_title(PurpleNotification *notification, const char *title) { PurpleNotificationPrivate *priv = NULL; g_return_if_fail(PURPLE_IS_NOTIFICATION(notification)); priv = purple_notification_get_instance_private(notification); if(g_set_str(&priv->title, title)) { g_object_notify_by_pspec(G_OBJECT(notification), properties[PROP_TITLE]); } } const char * purple_notification_get_subtitle(PurpleNotification *notification) { PurpleNotificationPrivate *priv = NULL; g_return_val_if_fail(PURPLE_IS_NOTIFICATION(notification), NULL); priv = purple_notification_get_instance_private(notification); return priv->subtitle; } void purple_notification_set_subtitle(PurpleNotification *notification, const char *subtitle) { PurpleNotificationPrivate *priv = NULL; g_return_if_fail(PURPLE_IS_NOTIFICATION(notification)); priv = purple_notification_get_instance_private(notification); if(g_set_str(&priv->subtitle, subtitle)) { g_object_notify_by_pspec(G_OBJECT(notification), properties[PROP_SUBTITLE]); } } const char * purple_notification_get_icon_name(PurpleNotification *notification) { PurpleNotificationPrivate *priv = NULL; g_return_val_if_fail(PURPLE_IS_NOTIFICATION(notification), NULL); priv = purple_notification_get_instance_private(notification); return priv->icon_name; } void purple_notification_set_icon_name(PurpleNotification *notification, const char *icon_name) { PurpleNotificationPrivate *priv = NULL; g_return_if_fail(PURPLE_IS_NOTIFICATION(notification)); priv = purple_notification_get_instance_private(notification); if(g_set_str(&priv->icon_name, icon_name)) { g_object_notify_by_pspec(G_OBJECT(notification), properties[PROP_ICON_NAME]); } } gboolean purple_notification_get_read(PurpleNotification *notification) { PurpleNotificationPrivate *priv = NULL; g_return_val_if_fail(PURPLE_IS_NOTIFICATION(notification), FALSE); priv = purple_notification_get_instance_private(notification); return priv->read; } void purple_notification_set_read(PurpleNotification *notification, gboolean read) { PurpleNotificationPrivate *priv = NULL; g_return_if_fail(PURPLE_IS_NOTIFICATION(notification)); priv = purple_notification_get_instance_private(notification); if(priv->read != read) { priv->read = read; g_object_notify_by_pspec(G_OBJECT(notification), properties[PROP_READ]); } } gboolean purple_notification_get_interactive(PurpleNotification *notification) { PurpleNotificationPrivate *priv = NULL; g_return_val_if_fail(PURPLE_IS_NOTIFICATION(notification), FALSE); priv = purple_notification_get_instance_private(notification); return priv->interactive; } void purple_notification_set_interactive(PurpleNotification *notification, gboolean interactive) { PurpleNotificationPrivate *priv = NULL; g_return_if_fail(PURPLE_IS_NOTIFICATION(notification)); priv = purple_notification_get_instance_private(notification); if(priv->interactive != interactive) { priv->interactive = interactive; g_object_notify_by_pspec(G_OBJECT(notification), properties[PROP_INTERACTIVE]); } } gboolean purple_notification_get_persistent(PurpleNotification *notification) { PurpleNotificationPrivate *priv = NULL; g_return_val_if_fail(PURPLE_IS_NOTIFICATION(notification), FALSE); priv = purple_notification_get_instance_private(notification); return priv->persistent; } void purple_notification_set_persistent(PurpleNotification *notification, gboolean persistent) { PurpleNotificationPrivate *priv = NULL; g_return_if_fail(PURPLE_IS_NOTIFICATION(notification)); priv = purple_notification_get_instance_private(notification); if(priv->persistent != persistent) { priv->persistent = persistent; g_object_notify_by_pspec(G_OBJECT(notification), properties[PROP_PERSISTENT]); } } int purple_notification_compare(gconstpointer a, gconstpointer b) { PurpleNotification *notification_a = NULL; PurpleNotification *notification_b = NULL; PurpleNotificationPrivate *priv_a = NULL; PurpleNotificationPrivate *priv_b = NULL; if(a == NULL && b == NULL) { return 0; } if(a == NULL) { return -1; } if(b == NULL) { return 1; } notification_a = (PurpleNotification *)a; notification_b = (PurpleNotification *)b; priv_a = purple_notification_get_instance_private(notification_a); priv_b = purple_notification_get_instance_private(notification_b); return g_date_time_compare(priv_a->created_timestamp, priv_b->created_timestamp); } void purple_notification_delete(PurpleNotification *notification) { PurpleNotificationPrivate *priv = NULL; g_return_if_fail(PURPLE_IS_NOTIFICATION(notification)); priv = purple_notification_get_instance_private(notification); /* Calling this multiple times is a programming error. */ g_return_if_fail(priv->deleted == FALSE); priv->deleted = TRUE; g_signal_emit(notification, signals[SIG_DELETED], 0); }