LCOV - code coverage report
Current view: top level - src/plugins/notification - valent-notification-upload.c (source / functions) Coverage Total Hit
Test: Code Coverage Lines: 76.3 % 198 151
Test Date: 2024-12-02 22:49:30 Functions: 93.8 % 16 15
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 43.2 % 176 76

             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-notification-upload"
       5                 :             : 
       6                 :             : #include "config.h"
       7                 :             : 
       8                 :             : #include <gio/gio.h>
       9                 :             : #include <gdk-pixbuf/gdk-pixbuf.h>
      10                 :             : #include <json-glib/json-glib.h>
      11                 :             : #include <valent.h>
      12                 :             : 
      13                 :             : #ifdef HAVE_GTK4
      14                 :             : #include <gtk/gtk.h>
      15                 :             : #endif /* HAVE_GTK4 */
      16                 :             : 
      17                 :             : #include "valent-notification-upload.h"
      18                 :             : 
      19                 :             : #define DEFAULT_ICON_SIZE 512
      20                 :             : 
      21                 :             : 
      22                 :             : /**
      23                 :             :  * ValentNotificationUpload:
      24                 :             :  *
      25                 :             :  * A class for notification icon uploads.
      26                 :             :  *
      27                 :             :  * `ValentNotificationUpload` is a class that abstracts uploading notifications
      28                 :             :  * with icon payloads for `ValentNotificationPlugin`.
      29                 :             :  */
      30                 :             : 
      31                 :             : struct _ValentNotificationUpload
      32                 :             : {
      33                 :             :   ValentTransfer  parent_instance;
      34                 :             : 
      35                 :             :   ValentDevice   *device;
      36                 :             :   JsonNode       *packet;
      37                 :             :   GIcon          *icon;
      38                 :             : };
      39                 :             : 
      40   [ +  +  +  - ]:          14 : G_DEFINE_FINAL_TYPE (ValentNotificationUpload, valent_notification_upload, VALENT_TYPE_TRANSFER)
      41                 :             : 
      42                 :             : enum {
      43                 :             :   PROP_0,
      44                 :             :   PROP_DEVICE,
      45                 :             :   PROP_ICON,
      46                 :             :   PROP_PACKET,
      47                 :             :   N_PROPERTIES,
      48                 :             : };
      49                 :             : 
      50                 :             : static GParamSpec *properties[N_PROPERTIES] = { 0, };
      51                 :             : 
      52                 :             : 
      53                 :             : #ifdef HAVE_GTK4
      54                 :             : static GtkIconTheme *
      55                 :           2 : _gtk_icon_theme_get_default (void)
      56                 :             : {
      57                 :           2 :   static GtkIconTheme *icon_theme = NULL;
      58                 :           2 :   size_t guard = 0;
      59                 :             : 
      60   [ +  -  +  - ]:           2 :   if (g_once_init_enter (&guard))
      61                 :             :     {
      62         [ -  + ]:           2 :       if (gtk_is_initialized ())
      63                 :             :         {
      64                 :           0 :           GdkDisplay *display = NULL;
      65                 :             : 
      66         [ #  # ]:           0 :           if ((display = gdk_display_get_default ()) != NULL)
      67                 :           0 :             icon_theme = gtk_icon_theme_get_for_display (display);
      68                 :             :         }
      69                 :             : 
      70                 :           2 :       g_once_init_leave (&guard, 1);
      71                 :             :     }
      72                 :             : 
      73                 :           2 :   return icon_theme;
      74                 :             : }
      75                 :             : 
      76                 :             : static int
      77                 :           0 : _gtk_icon_theme_get_largest_icon (GtkIconTheme *theme,
      78                 :             :                                   const char   *name)
      79                 :             : {
      80                 :           0 :   g_autofree int *sizes = NULL;
      81                 :           0 :   int ret = 0;
      82                 :             : 
      83   [ #  #  #  #  :           0 :   g_assert (GTK_IS_ICON_THEME (theme));
             #  #  #  # ]
      84         [ #  # ]:           0 :   g_assert (name != NULL);
      85                 :             : 
      86         [ #  # ]:           0 :   if (!gtk_icon_theme_has_icon (theme, name))
      87                 :             :     return ret;
      88                 :             : 
      89                 :           0 :   sizes = gtk_icon_theme_get_icon_sizes (theme, name);
      90                 :             : 
      91         [ #  # ]:           0 :   for (unsigned int i = 0; sizes[i] != 0; i++)
      92                 :             :     {
      93         [ #  # ]:           0 :       if (sizes[i] == -1)
      94                 :             :         return -1;
      95                 :             : 
      96                 :           0 :       if (sizes[i] > ret)
      97                 :             :         ret = sizes[i];
      98                 :             :     }
      99                 :             : 
     100                 :             :   return ret;
     101                 :             : }
     102                 :             : 
     103                 :             : static GFile *
     104                 :           2 : get_largest_icon_file (GIcon *icon)
     105                 :             : {
     106                 :           2 :   GtkIconTheme *icon_theme = NULL;
     107                 :           2 :   const char * const *names;
     108                 :           4 :   g_autoptr (GtkIconPaintable) info = NULL;
     109                 :             : 
     110   [ +  -  +  -  :           2 :   g_assert (G_IS_THEMED_ICON (icon));
             -  +  -  - ]
     111                 :             : 
     112                 :           2 :   icon_theme = _gtk_icon_theme_get_default ();
     113         [ -  + ]:           2 :   if (icon_theme == NULL)
     114                 :             :     return NULL;
     115                 :             : 
     116                 :           0 :   names = g_themed_icon_get_names (G_THEMED_ICON (icon));
     117         [ #  # ]:           0 :   for (size_t i = 0; names[i]; i++)
     118                 :             :     {
     119                 :           0 :       int size;
     120                 :             : 
     121                 :           0 :       size = _gtk_icon_theme_get_largest_icon (icon_theme, names[i]);
     122         [ #  # ]:           0 :       if (size == 0)
     123                 :           0 :         continue;
     124                 :             : 
     125                 :           0 :       info = gtk_icon_theme_lookup_icon (icon_theme,
     126                 :             :                                          names[i],
     127                 :             :                                          NULL,
     128                 :             :                                          size,
     129                 :             :                                          1,
     130                 :             :                                          GTK_TEXT_DIR_NONE,
     131                 :             :                                          0);
     132                 :             : 
     133         [ #  # ]:           0 :       if (info != NULL)
     134                 :           0 :         return gtk_icon_paintable_get_file (info);
     135                 :             :     }
     136                 :             : 
     137                 :             :   return NULL;
     138                 :             : }
     139                 :             : #endif /* HAVE_GTK4 */
     140                 :             : 
     141                 :             : static void
     142                 :           2 : on_size_prepared (GdkPixbufLoader *loader,
     143                 :             :                   int              width,
     144                 :             :                   int              height,
     145                 :             :                   gpointer         user_data)
     146                 :             : {
     147                 :           2 :   GdkPixbufFormat *format = gdk_pixbuf_loader_get_format (loader);
     148                 :             : 
     149         [ -  + ]:           2 :   if (!gdk_pixbuf_format_is_scalable (format))
     150                 :             :     return;
     151                 :             : 
     152         [ #  # ]:           0 :   if (width >= DEFAULT_ICON_SIZE || height >= DEFAULT_ICON_SIZE)
     153                 :             :     return;
     154                 :             : 
     155                 :           0 :   gdk_pixbuf_loader_set_size (loader, DEFAULT_ICON_SIZE, DEFAULT_ICON_SIZE);
     156                 :             : }
     157                 :             : 
     158                 :             : static GBytes *
     159                 :           4 : valent_notification_upload_get_icon_bytes (GIcon         *icon,
     160                 :             :                                            GCancellable  *cancellable,
     161                 :             :                                            GError       **error)
     162                 :             : {
     163                 :           8 :   g_autoptr (GBytes) bytes = NULL;
     164         [ +  + ]:           4 :   g_autoptr (GdkPixbufLoader) loader = NULL;
     165                 :           4 :   GdkPixbuf *pixbuf = NULL;
     166         [ +  + ]:           4 :   g_autoptr (GError) warn = NULL;
     167                 :           4 :   char *data;
     168                 :           4 :   size_t size;
     169                 :             : 
     170   [ +  -  +  -  :           4 :   g_assert (G_IS_ICON (icon));
             +  -  -  + ]
     171   [ +  -  +  -  :           4 :   g_assert (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
             -  +  -  - ]
     172   [ +  -  -  + ]:           4 :   g_assert (error == NULL || *error == NULL);
     173                 :             : 
     174                 :             :   /* First try to get the bytes of the GIcon */
     175   [ +  -  +  +  :           4 :   if (G_IS_THEMED_ICON (icon))
                   -  + ]
     176                 :             :     {
     177                 :           6 :       g_autoptr (GFile) file = NULL;
     178                 :             : 
     179                 :             : #ifdef HAVE_GTK4
     180                 :           2 :       file = get_largest_icon_file (icon);
     181         [ -  + ]:           2 :       if (file == NULL)
     182                 :             :         {
     183                 :           2 :           g_set_error (error,
     184                 :             :                        G_IO_ERROR,
     185                 :             :                        G_IO_ERROR_FAILED,
     186                 :             :                        "Failed to load themed icon");
     187                 :             :         }
     188                 :             : #else
     189                 :             :       g_set_error (error,
     190                 :             :                    G_IO_ERROR,
     191                 :             :                    G_IO_ERROR_NOT_SUPPORTED,
     192                 :             :                    "GTK is not initialized");
     193                 :             : #endif /* HAVE_GTK4 */
     194                 :             : 
     195                 :           2 :       if (file != NULL)
     196                 :           0 :         bytes = g_file_load_bytes (file, cancellable, NULL, error);
     197                 :             :     }
     198   [ +  -  +  +  :           2 :   else if (G_IS_FILE_ICON (icon))
                   -  + ]
     199                 :             :     {
     200                 :           1 :       GFile *file;
     201                 :             : 
     202                 :           1 :       file = g_file_icon_get_file (G_FILE_ICON (icon));
     203                 :           1 :       bytes = g_file_load_bytes (file, cancellable, NULL, error);
     204                 :             :     }
     205   [ +  -  -  +  :           1 :   else if (G_IS_BYTES_ICON (icon))
                   -  - ]
     206                 :             :     {
     207                 :           1 :       GBytes *buffer;
     208                 :             : 
     209                 :           1 :       buffer = g_bytes_icon_get_bytes (G_BYTES_ICON (icon));
     210                 :             : 
     211         [ -  + ]:           1 :       if (buffer == NULL)
     212                 :             :         {
     213                 :           0 :           g_set_error (error,
     214                 :             :                        G_IO_ERROR,
     215                 :             :                        G_IO_ERROR_FAILED,
     216                 :             :                        "Failed to load icon bytes");
     217                 :           0 :           return NULL;
     218                 :             :         }
     219                 :             : 
     220                 :           1 :       bytes = g_bytes_ref (buffer);
     221                 :             :     }
     222   [ #  #  #  #  :           0 :   else if (GDK_IS_PIXBUF (icon))
                   #  # ]
     223                 :             :     {
     224                 :           0 :       bytes = gdk_pixbuf_read_pixel_bytes (GDK_PIXBUF (icon));
     225                 :             :     }
     226                 :             : 
     227         [ +  + ]:           4 :   if (bytes == NULL)
     228                 :           2 :     return NULL;
     229                 :             : 
     230                 :             :   /* Now attempt to load the bytes as a pixbuf */
     231                 :           2 :   loader = gdk_pixbuf_loader_new ();
     232                 :             : 
     233                 :           2 :   g_signal_connect_object (loader,
     234                 :             :                            "size-prepared",
     235                 :             :                            G_CALLBACK (on_size_prepared),
     236                 :             :                            NULL, 0);
     237                 :             : 
     238   [ +  -  -  + ]:           4 :   if (!gdk_pixbuf_loader_write_bytes (loader, bytes, &warn) ||
     239                 :           2 :       !gdk_pixbuf_loader_close (loader, &warn))
     240                 :             :     {
     241                 :           0 :       g_debug ("%s(): %s", G_STRFUNC, warn->message);
     242                 :           0 :       return g_steal_pointer (&bytes);
     243                 :             :     }
     244                 :             : 
     245         [ -  + ]:           2 :   if ((pixbuf = gdk_pixbuf_loader_get_pixbuf (loader)) == NULL)
     246                 :             :     {
     247                 :           0 :       g_debug ("%s(): Failed to create pixbuf from bytes", G_STRFUNC);
     248                 :           0 :       return g_steal_pointer (&bytes);
     249                 :             :     }
     250                 :             : 
     251         [ -  + ]:           2 :   if (!gdk_pixbuf_save_to_buffer (pixbuf, &data, &size, "png", &warn, NULL))
     252                 :             :     {
     253                 :           0 :       g_debug ("%s(): %s", G_STRFUNC, warn->message);
     254                 :           0 :       return g_steal_pointer (&bytes);
     255                 :             :     }
     256                 :             : 
     257                 :           2 :   return g_bytes_new_take (data, size);
     258                 :             : }
     259                 :             : 
     260                 :             : /*
     261                 :             :  * ValentTransfer
     262                 :             :  */
     263                 :             : static void
     264                 :           4 : valent_notification_upload_execute_task (GTask        *task,
     265                 :             :                                          gpointer      source_object,
     266                 :             :                                          gpointer      task_data,
     267                 :             :                                          GCancellable *cancellable)
     268                 :             : {
     269                 :           4 :   ValentNotificationUpload *self = VALENT_NOTIFICATION_UPLOAD (source_object);
     270                 :           4 :   g_autoptr (ValentChannel) channel = NULL;
     271         [ +  - ]:           4 :   g_autoptr (GIcon) icon = NULL;
     272   [ +  -  +  - ]:           4 :   g_autoptr (JsonNode) packet = NULL;
     273   [ +  -  +  - ]:           4 :   g_autoptr (GBytes) bytes = NULL;
     274         [ -  + ]:           4 :   g_autoptr (GIOStream) target = NULL;
     275         [ -  + ]:           4 :   g_autofree char *payload_hash = NULL;
     276                 :           4 :   const uint8_t *payload_data = NULL;
     277                 :           4 :   size_t payload_size = 0;
     278                 :           4 :   gboolean ret = FALSE;
     279                 :           4 :   GError *error = NULL;
     280                 :             : 
     281         [ +  - ]:           4 :   g_assert (VALENT_IS_NOTIFICATION_UPLOAD (self));
     282                 :             : 
     283         [ +  - ]:           4 :   if (g_task_return_error_if_cancelled (task))
     284                 :             :     return;
     285                 :             : 
     286                 :           4 :   valent_object_lock (VALENT_OBJECT (self));
     287                 :           4 :   channel = valent_device_ref_channel (self->device);
     288                 :           4 :   icon = g_object_ref (self->icon);
     289                 :           4 :   packet = json_node_ref (self->packet);
     290                 :           4 :   valent_object_unlock (VALENT_OBJECT (self));
     291                 :             : 
     292         [ -  + ]:           4 :   if (channel == NULL)
     293                 :             :     {
     294                 :           0 :       g_task_return_new_error (task,
     295                 :             :                                G_IO_ERROR,
     296                 :             :                                G_IO_ERROR_NOT_CONNECTED,
     297                 :             :                                "Device is disconnected");
     298                 :           0 :       return;
     299                 :             :     }
     300                 :             : 
     301                 :             :   /* Try to get the icon bytes */
     302                 :           4 :   bytes = valent_notification_upload_get_icon_bytes (icon, cancellable, &error);
     303                 :             : 
     304         [ +  + ]:           4 :   if (bytes == NULL)
     305                 :           2 :     return g_task_return_error (task, error);
     306                 :             : 
     307                 :             :   /* A payload hash is included, allowing the remote device to ignore icon
     308                 :             :    * transfers that it already has cached. */
     309                 :           2 :   payload_data = g_bytes_get_data (bytes, &payload_size);
     310                 :           2 :   payload_hash = g_compute_checksum_for_data (G_CHECKSUM_MD5,
     311                 :             :                                               payload_data,
     312                 :             :                                               payload_size);
     313                 :           2 :   json_object_set_string_member (valent_packet_get_body (packet),
     314                 :             :                                  "payloadHash",
     315                 :             :                                  payload_hash);
     316                 :           2 :   valent_packet_set_payload_size (packet, payload_size);
     317                 :             : 
     318                 :           2 :   target = valent_channel_upload (channel, packet, cancellable, &error);
     319                 :             : 
     320         [ -  + ]:           2 :   if (target == NULL)
     321                 :           0 :     return g_task_return_error (task, error);
     322                 :             : 
     323                 :             :   /* Upload the icon */
     324                 :           2 :   ret = g_output_stream_write_all (g_io_stream_get_output_stream (target),
     325                 :             :                                    payload_data,
     326                 :             :                                    payload_size,
     327                 :             :                                    NULL,
     328                 :             :                                    cancellable,
     329                 :             :                                    &error);
     330                 :             : 
     331         [ -  + ]:           2 :   if (!ret)
     332                 :           0 :     return g_task_return_error (task, error);
     333                 :             : 
     334                 :           2 :   g_task_return_boolean (task, TRUE);
     335                 :             : }
     336                 :             : 
     337                 :             : static void
     338                 :           4 : valent_notification_upload_execute (ValentTransfer      *transfer,
     339                 :             :                                     GCancellable        *cancellable,
     340                 :             :                                     GAsyncReadyCallback  callback,
     341                 :             :                                     gpointer             user_data)
     342                 :             : {
     343                 :           8 :   g_autoptr (GTask) task = NULL;
     344                 :             : 
     345         [ +  - ]:           4 :   g_assert (VALENT_IS_NOTIFICATION_UPLOAD (transfer));
     346   [ +  -  +  -  :           4 :   g_assert (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
             -  +  -  - ]
     347                 :             : 
     348                 :           4 :   task = g_task_new (transfer, cancellable, callback, user_data);
     349         [ +  - ]:           4 :   g_task_set_source_tag (task, valent_notification_upload_execute);
     350         [ +  - ]:           4 :   g_task_run_in_thread (task, valent_notification_upload_execute_task);
     351                 :           4 : }
     352                 :             : 
     353                 :             : /*
     354                 :             :  * GObject
     355                 :             :  */
     356                 :             : static void
     357                 :           4 : valent_notification_upload_finalize (GObject *object)
     358                 :             : {
     359                 :           4 :   ValentNotificationUpload *self = VALENT_NOTIFICATION_UPLOAD (object);
     360                 :             : 
     361                 :           4 :   valent_object_lock (VALENT_OBJECT (self));
     362         [ +  - ]:           4 :   g_clear_object (&self->device);
     363         [ +  - ]:           4 :   g_clear_object (&self->icon);
     364         [ +  - ]:           4 :   g_clear_pointer (&self->packet, json_node_unref);
     365                 :           4 :   valent_object_unlock (VALENT_OBJECT (self));
     366                 :             : 
     367                 :           4 :   G_OBJECT_CLASS (valent_notification_upload_parent_class)->finalize (object);
     368                 :           4 : }
     369                 :             : 
     370                 :             : static void
     371                 :           4 : valent_notification_upload_get_property (GObject    *object,
     372                 :             :                                          guint       prop_id,
     373                 :             :                                          GValue     *value,
     374                 :             :                                          GParamSpec *pspec)
     375                 :             : {
     376                 :           4 :   ValentNotificationUpload *self = VALENT_NOTIFICATION_UPLOAD (object);
     377                 :             : 
     378   [ +  -  +  - ]:           4 :   switch (prop_id)
     379                 :             :     {
     380                 :             :     case PROP_DEVICE:
     381                 :           2 :       valent_object_lock (VALENT_OBJECT (self));
     382                 :           2 :       g_value_set_object (value, self->device);
     383                 :           2 :       valent_object_unlock (VALENT_OBJECT (self));
     384                 :           2 :       break;
     385                 :             : 
     386                 :             :     case PROP_ICON:
     387                 :           0 :       valent_object_lock (VALENT_OBJECT (self));
     388                 :           0 :       g_value_set_object (value, self->icon);
     389                 :           0 :       valent_object_unlock (VALENT_OBJECT (self));
     390                 :           0 :       break;
     391                 :             : 
     392                 :             :     case PROP_PACKET:
     393                 :           2 :       valent_object_lock (VALENT_OBJECT (self));
     394                 :           2 :       g_value_set_boxed (value, self->packet);
     395                 :           2 :       valent_object_unlock (VALENT_OBJECT (self));
     396                 :           2 :       break;
     397                 :             : 
     398                 :           0 :     default:
     399                 :           0 :       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     400                 :             :     }
     401                 :           4 : }
     402                 :             : 
     403                 :             : static void
     404                 :          12 : valent_notification_upload_set_property (GObject      *object,
     405                 :             :                                          guint         prop_id,
     406                 :             :                                          const GValue *value,
     407                 :             :                                          GParamSpec   *pspec)
     408                 :             : {
     409                 :          12 :   ValentNotificationUpload *self = VALENT_NOTIFICATION_UPLOAD (object);
     410                 :             : 
     411   [ +  +  +  - ]:          12 :   switch (prop_id)
     412                 :             :     {
     413                 :             :     case PROP_DEVICE:
     414                 :           4 :       valent_object_lock (VALENT_OBJECT (self));
     415                 :           4 :       self->device = g_value_dup_object (value);
     416                 :           4 :       valent_object_unlock (VALENT_OBJECT (self));
     417                 :           4 :       break;
     418                 :             : 
     419                 :             :     case PROP_ICON:
     420                 :           4 :       valent_object_lock (VALENT_OBJECT (self));
     421                 :           4 :       self->icon = g_value_dup_object (value);
     422                 :           4 :       valent_object_unlock (VALENT_OBJECT (self));
     423                 :           4 :       break;
     424                 :             : 
     425                 :             :     case PROP_PACKET:
     426                 :           4 :       valent_object_lock (VALENT_OBJECT (self));
     427                 :           4 :       self->packet = g_value_dup_boxed (value);
     428                 :           4 :       valent_object_unlock (VALENT_OBJECT (self));
     429                 :           4 :       break;
     430                 :             : 
     431                 :           0 :     default:
     432                 :           0 :       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     433                 :             :     }
     434                 :          12 : }
     435                 :             : 
     436                 :             : static void
     437                 :           1 : valent_notification_upload_class_init (ValentNotificationUploadClass *klass)
     438                 :             : {
     439                 :           1 :   GObjectClass *object_class = G_OBJECT_CLASS (klass);
     440                 :           1 :   ValentTransferClass *transfer_class = VALENT_TRANSFER_CLASS (klass);
     441                 :             : 
     442                 :           1 :   object_class->finalize = valent_notification_upload_finalize;
     443                 :           1 :   object_class->get_property = valent_notification_upload_get_property;
     444                 :           1 :   object_class->set_property = valent_notification_upload_set_property;
     445                 :             : 
     446                 :           1 :   transfer_class->execute = valent_notification_upload_execute;
     447                 :             : 
     448                 :             :   /**
     449                 :             :    * ValentNotificationUpload:device:
     450                 :             :    *
     451                 :             :    * The [class@Valent.Device] this transfer is for.
     452                 :             :    */
     453                 :           2 :   properties [PROP_DEVICE] =
     454                 :           1 :     g_param_spec_object ("device", NULL, NULL,
     455                 :             :                          VALENT_TYPE_DEVICE,
     456                 :             :                          (G_PARAM_READWRITE |
     457                 :             :                           G_PARAM_CONSTRUCT_ONLY |
     458                 :             :                           G_PARAM_EXPLICIT_NOTIFY |
     459                 :             :                           G_PARAM_STATIC_STRINGS));
     460                 :             : 
     461                 :             :   /**
     462                 :             :    * ValentNotificationUpload:icon:
     463                 :             :    *
     464                 :             :    * The [iface@Gio.Icon] for the notification.
     465                 :             :    */
     466                 :           2 :   properties [PROP_ICON] =
     467                 :           1 :     g_param_spec_object ("icon", NULL, NULL,
     468                 :             :                          G_TYPE_ICON,
     469                 :             :                          (G_PARAM_READWRITE |
     470                 :             :                           G_PARAM_CONSTRUCT_ONLY |
     471                 :             :                           G_PARAM_EXPLICIT_NOTIFY |
     472                 :             :                           G_PARAM_STATIC_STRINGS));
     473                 :             : 
     474                 :             :   /**
     475                 :             :    * ValentNotificationUpload:packet:
     476                 :             :    *
     477                 :             :    * The packet to send the payload with.
     478                 :             :    */
     479                 :           2 :   properties [PROP_PACKET] =
     480                 :           1 :     g_param_spec_boxed ("packet", NULL, NULL,
     481                 :             :                         JSON_TYPE_NODE,
     482                 :             :                         (G_PARAM_READWRITE |
     483                 :             :                          G_PARAM_CONSTRUCT_ONLY |
     484                 :             :                          G_PARAM_EXPLICIT_NOTIFY |
     485                 :             :                          G_PARAM_STATIC_STRINGS));
     486                 :             : 
     487                 :           1 :   g_object_class_install_properties (object_class, N_PROPERTIES, properties);
     488                 :           1 : }
     489                 :             : 
     490                 :             : static void
     491                 :           4 : valent_notification_upload_init (ValentNotificationUpload *self)
     492                 :             : {
     493                 :           4 : }
     494                 :             : 
     495                 :             : /**
     496                 :             :  * valent_notification_upload_new:
     497                 :             :  * @device: a `ValentDevice`
     498                 :             :  * @packet: a KDE Connect packet
     499                 :             :  * @icon: a `GIcon`
     500                 :             :  *
     501                 :             :  * Create a new `ValentNotificationUpload` for @packet and @icon.
     502                 :             :  *
     503                 :             :  * Returns: (transfer full): a `ValentNotificationUpload`
     504                 :             :  */
     505                 :             : ValentTransfer *
     506                 :           4 : valent_notification_upload_new (ValentDevice *device,
     507                 :             :                                 JsonNode     *packet,
     508                 :             :                                 GIcon        *icon)
     509                 :             : {
     510         [ +  - ]:           4 :   g_return_val_if_fail (VALENT_IS_DEVICE (device), NULL);
     511         [ -  + ]:           4 :   g_return_val_if_fail (VALENT_IS_PACKET (packet), NULL);
     512   [ +  -  +  -  :           4 :   g_return_val_if_fail (G_IS_ICON (icon), NULL);
             +  -  -  + ]
     513                 :             : 
     514                 :           4 :   return g_object_new (VALENT_TYPE_NOTIFICATION_UPLOAD,
     515                 :             :                        "device", device,
     516                 :             :                        "icon",   icon,
     517                 :             :                        "packet", packet,
     518                 :             :                        NULL);
     519                 :             : }
     520                 :             : 
        

Generated by: LCOV version 2.0-1