Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-3.0-or-later
2 : : // SPDX-FileCopyrightText: Andy Holmes <andrew.g.r.holmes@gmail.com>
3 : :
4 : : #define G_LOG_DOMAIN "valent-notifications-adapter"
5 : :
6 : : #include "config.h"
7 : :
8 : : #include <libvalent-core.h>
9 : :
10 : : #include "valent-notification.h"
11 : : #include "valent-notifications-adapter.h"
12 : :
13 : :
14 : : /**
15 : : * ValentNotificationsAdapter:
16 : : *
17 : : * An abstract base class for notification servers.
18 : : *
19 : : * `ValentNotificationsAdapter` is a base class for notification servers. This
20 : : * usually means monitoring a D-Bus service for notifications being sent and
21 : : * withdrawn.
22 : : *
23 : : * ## `.plugin` File
24 : : *
25 : : * Implementations may define the following extra fields in the `.plugin` file:
26 : : *
27 : : * - `X-NotificationsAdapterPriority`
28 : : *
29 : : * An integer indicating the adapter priority. The implementation with the
30 : : * lowest value will be used as the primary adapter.
31 : : *
32 : : * Since: 1.0
33 : : */
34 : :
35 : : typedef struct
36 : : {
37 : : GPtrArray *items;
38 : : } ValentNotificationsAdapterPrivate;
39 : :
40 : : static void g_list_model_iface_init (GListModelInterface *iface);
41 : :
42 [ + + + - ]: 451 : G_DEFINE_ABSTRACT_TYPE_WITH_CODE (ValentNotificationsAdapter, valent_notifications_adapter, VALENT_TYPE_EXTENSION,
43 : : G_ADD_PRIVATE (ValentNotificationsAdapter)
44 : : G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL, g_list_model_iface_init))
45 : :
46 : : /*
47 : : * GListModel
48 : : */
49 : : static gpointer
50 : 27 : valent_notifications_adapter_get_item (GListModel *list,
51 : : unsigned int position)
52 : : {
53 : 27 : ValentNotificationsAdapter *self = VALENT_NOTIFICATIONS_ADAPTER (list);
54 : 27 : ValentNotificationsAdapterPrivate *priv = valent_notifications_adapter_get_instance_private (self);
55 : :
56 [ - + ]: 27 : g_assert (VALENT_IS_NOTIFICATIONS_ADAPTER (self));
57 : :
58 [ + - ]: 27 : if G_UNLIKELY (position >= priv->items->len)
59 : : return NULL;
60 : :
61 : 27 : return g_object_ref (g_ptr_array_index (priv->items, position));
62 : : }
63 : :
64 : : static GType
65 : 1 : valent_notifications_adapter_get_item_type (GListModel *list)
66 : : {
67 : 1 : return VALENT_TYPE_NOTIFICATION;
68 : : }
69 : :
70 : : static unsigned int
71 : 7 : valent_notifications_adapter_get_n_items (GListModel *list)
72 : : {
73 : 7 : ValentNotificationsAdapter *self = VALENT_NOTIFICATIONS_ADAPTER (list);
74 : 7 : ValentNotificationsAdapterPrivate *priv = valent_notifications_adapter_get_instance_private (self);
75 : :
76 [ - + ]: 7 : g_assert (VALENT_IS_NOTIFICATIONS_ADAPTER (self));
77 : :
78 : 7 : return priv->items->len;
79 : : }
80 : :
81 : : static void
82 : 52 : g_list_model_iface_init (GListModelInterface *iface)
83 : : {
84 : 52 : iface->get_item = valent_notifications_adapter_get_item;
85 : 52 : iface->get_item_type = valent_notifications_adapter_get_item_type;
86 : 52 : iface->get_n_items = valent_notifications_adapter_get_n_items;
87 : 52 : }
88 : :
89 : : /*
90 : : * GObject
91 : : */
92 : : static void
93 : 4 : valent_notifications_adapter_finalize (GObject *object)
94 : : {
95 : 4 : ValentNotificationsAdapter *self = VALENT_NOTIFICATIONS_ADAPTER (object);
96 : 4 : ValentNotificationsAdapterPrivate *priv = valent_notifications_adapter_get_instance_private (self);
97 : :
98 [ + - ]: 4 : g_clear_pointer (&priv->items, g_ptr_array_unref);
99 : :
100 : 4 : G_OBJECT_CLASS (valent_notifications_adapter_parent_class)->finalize (object);
101 : 4 : }
102 : :
103 : : static void
104 : 52 : valent_notifications_adapter_class_init (ValentNotificationsAdapterClass *klass)
105 : : {
106 : 52 : GObjectClass *object_class = G_OBJECT_CLASS (klass);
107 : :
108 : 52 : object_class->finalize = valent_notifications_adapter_finalize;
109 : : }
110 : :
111 : : static void
112 : 10 : valent_notifications_adapter_init (ValentNotificationsAdapter *adapter)
113 : : {
114 : 10 : ValentNotificationsAdapterPrivate *priv = valent_notifications_adapter_get_instance_private (adapter);
115 : :
116 : 10 : priv->items = g_ptr_array_new_with_free_func (g_object_unref);
117 : 10 : }
118 : :
119 : : /**
120 : : * valent_notifications_adapter_notification_added:
121 : : * @adapter: a `ValentNotificationsAdapter`
122 : : * @notification: a `ValentNotification`
123 : : *
124 : : * Called when @notification has been added to @adapter.
125 : : *
126 : : * This method should only be called by implementations of
127 : : * [class@Valent.NotificationsAdapter]. @adapter will hold a reference on
128 : : * @notification and emit [signal@Gio.ListModel::items-changed].
129 : : *
130 : : * Since: 1.0
131 : : */
132 : : void
133 : 9 : valent_notifications_adapter_notification_added (ValentNotificationsAdapter *adapter,
134 : : ValentNotification *notification)
135 : : {
136 : 9 : ValentNotificationsAdapterPrivate *priv = valent_notifications_adapter_get_instance_private (adapter);
137 : 9 : unsigned int position = 0;
138 : :
139 [ - + ]: 9 : g_return_if_fail (VALENT_IS_NOTIFICATIONS_ADAPTER (adapter));
140 [ + - ]: 9 : g_return_if_fail (VALENT_IS_NOTIFICATION (notification));
141 : :
142 : 9 : position = priv->items->len;
143 : 9 : g_ptr_array_add (priv->items, g_object_ref (notification));
144 : 9 : g_list_model_items_changed (G_LIST_MODEL (adapter), position, 0, 1);
145 : : }
146 : :
147 : : /**
148 : : * valent_notifications_adapter_notification_removed:
149 : : * @adapter: a `ValentNotificationsAdapter`
150 : : * @notification: a `ValentNotification`
151 : : *
152 : : * Called when @notification has been removed from @adapter.
153 : : *
154 : : * This method should only be called by implementations of
155 : : * [class@Valent.NotificationsAdapter]. @adapter will drop its reference on
156 : : * @notification and emit [signal@Gio.ListModel::items-changed].
157 : : *
158 : : * Since: 1.0
159 : : */
160 : : void
161 : 5 : valent_notifications_adapter_notification_removed (ValentNotificationsAdapter *adapter,
162 : : ValentNotification *notification)
163 : : {
164 : 5 : ValentNotificationsAdapterPrivate *priv = valent_notifications_adapter_get_instance_private (adapter);
165 : 5 : g_autoptr (ValentNotification) item = NULL;
166 : 5 : unsigned int position = 0;
167 : :
168 [ - + ]: 5 : g_return_if_fail (VALENT_IS_NOTIFICATIONS_ADAPTER (adapter));
169 [ + - ]: 5 : g_return_if_fail (VALENT_IS_NOTIFICATION (notification));
170 : :
171 [ + - ]: 5 : if (!g_ptr_array_find (priv->items, notification, &position))
172 : : return;
173 : :
174 : 5 : item = g_ptr_array_steal_index (priv->items, position);
175 : 5 : g_list_model_items_changed (G_LIST_MODEL (adapter), position, 1, 0);
176 : :
177 : : // TODO: avoid relying on the destroy signal with a state property
178 [ + - ]: 5 : valent_object_destroy (VALENT_OBJECT (notification));
179 : : }
180 : :
|