LCOV - code coverage report
Current view: top level - malcontent-control - screen-time-statistics-row.c (source / functions) Coverage Total Hit
Test: 2 coverage DB files Lines: 0.0 % 160 0
Test Date: 2025-10-05 20:47:42 Functions: 0.0 % 19 0
Branches: 0.0 % 58 0

             Branch data     Line data    Source code
       1                 :             : /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
       2                 :             :  *
       3                 :             :  * Copyright 2025 GNOME Foundation, Inc.
       4                 :             :  *
       5                 :             :  * SPDX-License-Identifier: GPL-2.0-or-later
       6                 :             :  *
       7                 :             :  * This program is free software; you can redistribute it and/or modify
       8                 :             :  * it under the terms of the GNU General Public License as published by
       9                 :             :  * the Free Software Foundation; either version 2 of the License, or
      10                 :             :  * (at your option) any later version.
      11                 :             :  *
      12                 :             :  * This program is distributed in the hope that it will be useful,
      13                 :             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14                 :             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15                 :             :  * GNU General Public License for more details.
      16                 :             :  *
      17                 :             :  * You should have received a copy of the GNU General Public License
      18                 :             :  * along with this program; if not, see <http://www.gnu.org/licenses/>.
      19                 :             :  *
      20                 :             :  * Authors:
      21                 :             :  *  - Ignacy Kuchciński <ignacykuchcinski@gnome.org>
      22                 :             :  */
      23                 :             : 
      24                 :             : #include "config.h"
      25                 :             : 
      26                 :             : #include <glib/gi18n.h>
      27                 :             : #include <stdint.h>
      28                 :             : 
      29                 :             : #include "screen-time-statistics-row.h"
      30                 :             : 
      31                 :             : /**
      32                 :             :  * MctScreenTimeStatisticsRow:
      33                 :             :  *
      34                 :             :  * A widget which shows screen time bar chart for screen time usage
      35                 :             :  * records for the selected user.
      36                 :             :  *
      37                 :             :  * Since: 0.14.0
      38                 :             :  */
      39                 :             : struct _MctScreenTimeStatisticsRow
      40                 :             : {
      41                 :             :   CcScreenTimeStatisticsRow parent;
      42                 :             : 
      43                 :             :   GDBusConnection *connection; /* (owned) */
      44                 :             :   uid_t uid;
      45                 :             : };
      46                 :             : 
      47   [ #  #  #  #  :           0 : G_DEFINE_TYPE (MctScreenTimeStatisticsRow, mct_screen_time_statistics_row, CC_TYPE_SCREEN_TIME_STATISTICS_ROW)
                   #  # ]
      48                 :             : 
      49                 :             : typedef enum
      50                 :             : {
      51                 :             :   PROP_CONNECTION = 1,
      52                 :             :   PROP_UID,
      53                 :             : } MctScreenTimeStatisticsRowProperty;
      54                 :             : 
      55                 :             : static GParamSpec *properties[PROP_UID + 1];
      56                 :             : 
      57                 :             : static void
      58                 :           0 : mct_screen_time_statistics_row_get_property (GObject      *object,
      59                 :             :                                              unsigned int  property_id,
      60                 :             :                                              GValue       *value,
      61                 :             :                                              GParamSpec   *spec)
      62                 :             : {
      63                 :           0 :   MctScreenTimeStatisticsRow *self = MCT_SCREEN_TIME_STATISTICS_ROW (object);
      64                 :             : 
      65      [ #  #  # ]:           0 :   switch ((MctScreenTimeStatisticsRowProperty) property_id)
      66                 :             :   {
      67                 :           0 :     case PROP_CONNECTION:
      68                 :           0 :       g_value_set_object (value, self->connection);
      69                 :           0 :       break;
      70                 :             : 
      71                 :           0 :     case PROP_UID:
      72                 :           0 :       g_value_set_uint (value, self->uid);
      73                 :           0 :       break;
      74                 :             : 
      75                 :           0 :     default:
      76                 :           0 :       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, spec);
      77                 :           0 :       break;
      78                 :             :   }
      79                 :           0 : }
      80                 :             : 
      81                 :             : static void
      82                 :           0 : mct_screen_time_statistics_row_set_property (GObject      *object,
      83                 :             :                                              unsigned int  property_id,
      84                 :             :                                              const GValue *value,
      85                 :             :                                              GParamSpec   *spec)
      86                 :             : {
      87                 :           0 :   MctScreenTimeStatisticsRow *self = MCT_SCREEN_TIME_STATISTICS_ROW (object);
      88                 :             : 
      89      [ #  #  # ]:           0 :   switch ((MctScreenTimeStatisticsRowProperty) property_id)
      90                 :             :   {
      91                 :           0 :     case PROP_CONNECTION:
      92                 :             :       /* Construct-only. May not be %NULL. */
      93                 :           0 :       g_assert (self->connection == NULL);
      94                 :           0 :       self->connection = g_value_dup_object (value);
      95                 :           0 :       g_assert (self->connection != NULL);
      96                 :           0 :       break;
      97                 :             : 
      98                 :           0 :     case PROP_UID:
      99                 :             :       /* Construct-only. */
     100                 :           0 :       g_assert (self->uid == 0);
     101                 :           0 :       self->uid = g_value_get_uint (value);
     102                 :           0 :       g_assert (self->uid != 0);
     103                 :           0 :       break;
     104                 :             : 
     105                 :           0 :     default:
     106                 :           0 :       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, spec);
     107                 :           0 :       break;
     108                 :             :   }
     109                 :           0 : }
     110                 :             : 
     111                 :             : static void
     112                 :           0 : mct_screen_time_statistics_row_constructed (GObject *object)
     113                 :             : {
     114                 :           0 :   MctScreenTimeStatisticsRow *self = MCT_SCREEN_TIME_STATISTICS_ROW (object);
     115                 :             : 
     116                 :           0 :   g_assert (self->connection != NULL);
     117                 :           0 :   g_assert (self->uid != 0);
     118                 :             : 
     119                 :           0 :   G_OBJECT_CLASS (mct_screen_time_statistics_row_parent_class)->constructed (object);
     120                 :           0 : }
     121                 :             : 
     122                 :             : static void
     123                 :           0 : mct_screen_time_statistics_row_dispose (GObject *object)
     124                 :             : {
     125                 :           0 :   MctScreenTimeStatisticsRow *self = MCT_SCREEN_TIME_STATISTICS_ROW (object);
     126                 :             : 
     127         [ #  # ]:           0 :   g_clear_object (&self->connection);
     128                 :             : 
     129                 :           0 :   G_OBJECT_CLASS (mct_screen_time_statistics_row_parent_class)->dispose (object);
     130                 :           0 : }
     131                 :             : 
     132                 :             : typedef struct
     133                 :             : {
     134                 :             :   GDate *start_date;
     135                 :             :   size_t n_days;
     136                 :             :   double *screen_time_per_day;
     137                 :             : } LoadDataData;
     138                 :             : 
     139                 :             : static void
     140                 :           0 : load_data_data_free (LoadDataData *data)
     141                 :             : {
     142                 :           0 :   g_date_free (data->start_date);
     143                 :           0 :   g_free (data->screen_time_per_day);
     144                 :           0 :   g_free (data);
     145                 :           0 : }
     146                 :             : 
     147         [ #  # ]:           0 : G_DEFINE_AUTOPTR_CLEANUP_FUNC (LoadDataData, load_data_data_free)
     148                 :             : 
     149                 :             : /**
     150                 :             :  * load_data_data_new:
     151                 :             :  * @start_date: (transfer none): an initialized #GDate
     152                 :             :  * @n_days: number of days
     153                 :             :  * @screen_time_per_day: (transfer full): screen time per day
     154                 :             :  */
     155                 :             : static LoadDataData *
     156                 :           0 : load_data_data_new (GDate  *start_date,
     157                 :             :                     size_t  n_days,
     158                 :             :                     double *screen_time_per_day)
     159                 :             : {
     160                 :           0 :   g_autoptr(LoadDataData) data = g_new0 (LoadDataData, 1);
     161                 :             : 
     162                 :           0 :   data->start_date = g_date_copy (start_date);
     163                 :           0 :   data->n_days = n_days;
     164                 :           0 :   data->screen_time_per_day = screen_time_per_day;
     165                 :             : 
     166                 :           0 :   return g_steal_pointer (&data);
     167                 :             : }
     168                 :             : 
     169                 :             : static void
     170                 :             : query_usage_cb (GObject      *object,
     171                 :             :                 GAsyncResult *result,
     172                 :             :                 void         *user_data);
     173                 :             : 
     174                 :             : static void
     175                 :           0 : mct_screen_time_statistics_row_load_data_async (CcScreenTimeStatisticsRow *screen_time_statistics_row,
     176                 :             :                                                 GCancellable              *cancellable,
     177                 :             :                                                 GAsyncReadyCallback        callback,
     178                 :             :                                                 void                      *user_data)
     179                 :             : {
     180                 :           0 :   MctScreenTimeStatisticsRow *self = MCT_SCREEN_TIME_STATISTICS_ROW (screen_time_statistics_row);
     181                 :           0 :   g_autoptr(GTask) task = NULL;
     182                 :             : 
     183                 :           0 :   task = g_task_new (self, cancellable, callback, user_data);
     184         [ #  # ]:           0 :   g_task_set_source_tag (task, mct_screen_time_statistics_row_load_data_async);
     185                 :             : 
     186                 :             :   /* Load and parse the screen time usage periods of the child account using
     187                 :             :    * the org.freedesktop.MalcontentTimer1.Parent malcontent-timerd interface.
     188                 :             :    * See `timeLimitsManager.js` in gnome-shell for the code which records the
     189                 :             :    * usage using org.freedesktop.MalcontentTimer1.Child interface. */
     190                 :           0 :   g_dbus_connection_call (self->connection,
     191                 :             :                           "org.freedesktop.MalcontentTimer1",
     192                 :             :                           "/org/freedesktop/MalcontentTimer1",
     193                 :             :                           "org.freedesktop.MalcontentTimer1.Parent",
     194                 :             :                           "QueryUsage",
     195                 :             :                           g_variant_new ("(uss)",
     196                 :             :                                          self->uid,
     197                 :             :                                          "login-session",
     198                 :             :                                          ""),
     199                 :             :                           (const GVariantType *) "(a(tt))",
     200                 :             :                           G_DBUS_CALL_FLAGS_NONE,
     201                 :             :                           -1,
     202                 :             :                           cancellable,
     203                 :             :                           query_usage_cb,
     204                 :             :                           g_steal_pointer (&task));
     205                 :           0 : }
     206                 :             : 
     207                 :             : static void allocate_duration_to_days (const GDate *model_start_date,
     208                 :             :                                        GArray      *model_screen_time_per_day,
     209                 :             :                                        uint64_t     start_wall_time_secs,
     210                 :             :                                        uint64_t     duration_secs);
     211                 :             : 
     212                 :             : static void
     213                 :           0 : query_usage_cb (GObject      *object,
     214                 :             :                 GAsyncResult *result,
     215                 :             :                 void         *user_data)
     216                 :             : {
     217                 :           0 :   GDBusConnection *connection = G_DBUS_CONNECTION (object);
     218         [ #  # ]:           0 :   g_autoptr(GTask) task = G_TASK (g_steal_pointer (&user_data));
     219                 :             :   GDate new_model_start_date;
     220                 :             :   size_t new_model_n_days;
     221         [ #  # ]:           0 :   g_autoptr(GArray) new_model_screen_time_per_day = NULL;  /* (element-type double) */
     222         [ #  # ]:           0 :   g_autoptr(GVariant) result_variant = NULL;
     223         [ #  # ]:           0 :   g_autoptr(GError) local_error = NULL;
     224         [ #  # ]:           0 :   g_autoptr(GVariantIter) entries_iter = NULL;
     225                 :             :   uint64_t start_wall_time_secs, end_wall_time_secs;
     226                 :             : 
     227                 :           0 :   g_date_clear (&new_model_start_date, 1);
     228                 :             : 
     229                 :           0 :   result_variant = g_dbus_connection_call_finish (connection, result, &local_error);
     230                 :             : 
     231         [ #  # ]:           0 :   if (result_variant == NULL)
     232                 :             :     {
     233                 :           0 :       g_task_return_error (task, g_steal_pointer (&local_error));
     234                 :           0 :       return;
     235                 :             :     }
     236                 :             : 
     237                 :           0 :   g_variant_get (result_variant, "(a(tt))", &entries_iter);
     238         [ #  # ]:           0 :   while (g_variant_iter_loop (entries_iter, "(tt)", &start_wall_time_secs, &end_wall_time_secs))
     239                 :             :     {
     240                 :             :       /* Set up the model if this is the first iteration */
     241         [ #  # ]:           0 :       if (!g_date_valid (&new_model_start_date))
     242                 :             :         {
     243                 :           0 :           g_date_set_time_t (&new_model_start_date, start_wall_time_secs);
     244                 :           0 :           new_model_screen_time_per_day = g_array_new (FALSE, TRUE, sizeof (double));
     245                 :             :         }
     246                 :             : 
     247                 :             :       /* Interpret the data */
     248                 :           0 :       uint64_t duration_secs = end_wall_time_secs - start_wall_time_secs;
     249                 :           0 :       allocate_duration_to_days (&new_model_start_date, new_model_screen_time_per_day,
     250                 :             :                                  start_wall_time_secs, duration_secs);
     251                 :             :     }
     252                 :             : 
     253                 :             :   /* Was the data empty? */
     254   [ #  #  #  # ]:           0 :   if (new_model_screen_time_per_day == NULL || new_model_screen_time_per_day->len == 0)
     255                 :             :     {
     256                 :           0 :       g_set_error (&local_error, G_FILE_ERROR, G_FILE_ERROR_NOENT,
     257                 :           0 :                    _("Failed to load session history data: %s"),
     258                 :             :                    _("Data is empty"));
     259                 :           0 :       g_task_return_error (task, g_steal_pointer (&local_error));
     260                 :           0 :       return;
     261                 :             :     }
     262                 :             : 
     263                 :           0 :   new_model_n_days = new_model_screen_time_per_day->len;
     264                 :             : 
     265                 :           0 :   LoadDataData *data = load_data_data_new (&new_model_start_date,
     266                 :             :                                            new_model_n_days,
     267                 :           0 :                                            (double *) g_array_free (g_steal_pointer (&new_model_screen_time_per_day), FALSE));
     268                 :           0 :   g_task_return_pointer (task, data, (GDestroyNotify) load_data_data_free);
     269                 :             : }
     270                 :             : 
     271                 :             : static void allocate_duration_to_day (const GDate *model_start_date,
     272                 :             :                                       GArray      *model_screen_time_per_day,
     273                 :             :                                       GDateTime   *start_date_time,
     274                 :             :                                       uint64_t     duration_secs);
     275                 :             : 
     276                 :             : /* Take the time period [start_wall_time_secs, start_wall_time_secs + duration_secs]
     277                 :             :  * and add it to the model, splitting it between day boundaries if needed, and
     278                 :             :  * extending the `GArray` if needed. */
     279                 :             : static void
     280                 :           0 : allocate_duration_to_days (const GDate *model_start_date,
     281                 :             :                            GArray      *model_screen_time_per_day,
     282                 :             :                            uint64_t     start_wall_time_secs,
     283                 :             :                            uint64_t     duration_secs)
     284                 :             : {
     285                 :           0 :   g_autoptr(GDateTime) start_date_time = NULL;
     286                 :             : 
     287                 :           0 :   start_date_time = g_date_time_new_from_unix_local (start_wall_time_secs);
     288                 :             : 
     289         [ #  # ]:           0 :   while (duration_secs > 0)
     290                 :             :     {
     291                 :           0 :       g_autoptr(GDateTime) start_of_day = NULL, start_of_next_day = NULL;
     292                 :           0 :       g_autoptr(GDateTime) new_start_date_time = NULL;
     293                 :             :       GTimeSpan span_usecs;
     294                 :             :       uint64_t span_secs;
     295                 :             : 
     296                 :           0 :       start_of_day = g_date_time_new_local (g_date_time_get_year (start_date_time),
     297                 :             :                                             g_date_time_get_month (start_date_time),
     298                 :             :                                             g_date_time_get_day_of_month (start_date_time),
     299                 :             :                                             0, 0, 0);
     300                 :           0 :       g_assert (start_of_day != NULL);
     301                 :           0 :       start_of_next_day = g_date_time_add_days (start_of_day, 1);
     302                 :           0 :       g_assert (start_of_next_day != NULL);
     303                 :             : 
     304                 :           0 :       span_usecs = g_date_time_difference (start_of_next_day, start_date_time);
     305                 :           0 :       span_secs = span_usecs / G_USEC_PER_SEC;
     306         [ #  # ]:           0 :       if (span_secs > duration_secs)
     307                 :           0 :         span_secs = duration_secs;
     308                 :             : 
     309                 :           0 :       allocate_duration_to_day (model_start_date, model_screen_time_per_day,
     310                 :             :                                 start_date_time, span_secs);
     311                 :             : 
     312                 :           0 :       duration_secs -= span_secs;
     313                 :           0 :       new_start_date_time = g_date_time_add_seconds (start_date_time, span_secs);
     314                 :           0 :       g_date_time_unref (start_date_time);
     315                 :           0 :       start_date_time = g_steal_pointer (&new_start_date_time);
     316                 :             :     }
     317                 :           0 : }
     318                 :             : 
     319                 :             : /* Take the time period [start_date_time, start_date_time + duration_secs]
     320                 :             :  * and add it to the model, extending the `GArray` if needed. The time period
     321                 :             :  * *must not* cross a day boundary, i.e. it’s invalid to call this function
     322                 :             :  * with `start_date_time` as 23:00 on a day, and `duration_secs` as 2h.
     323                 :             :  *
     324                 :             :  * Note that @model_screen_time_per_day is in minutes, whereas @duration_secs
     325                 :             :  * is in seconds. */
     326                 :             : static void
     327                 :           0 : allocate_duration_to_day (const GDate *model_start_date,
     328                 :             :                           GArray      *model_screen_time_per_day,
     329                 :             :                           GDateTime   *start_date_time,
     330                 :             :                           uint64_t     duration_secs)
     331                 :             : {
     332                 :             :   GDate start_date;
     333                 :             :   int diff_days;
     334                 :             :   double *element;
     335                 :             : 
     336                 :           0 :   g_date_clear (&start_date, 1);
     337                 :           0 :   g_date_set_dmy (&start_date,
     338                 :           0 :                   g_date_time_get_day_of_month (start_date_time),
     339                 :           0 :                   g_date_time_get_month (start_date_time),
     340                 :           0 :                   g_date_time_get_year (start_date_time));
     341                 :             : 
     342                 :           0 :   diff_days = g_date_days_between (model_start_date, &start_date);
     343                 :           0 :   g_assert (diff_days >= 0);
     344                 :             : 
     345                 :             :   /* If the new day is outside the range of the model, insert it at the right
     346                 :             :    * index. This will automatically create the indices between, and initialise
     347                 :             :    * them to zero, which is what we want. */
     348         [ #  # ]:           0 :   if ((unsigned int) diff_days >= model_screen_time_per_day->len)
     349                 :             :     {
     350                 :           0 :       const double new_val = 0.0;
     351                 :           0 :       g_array_insert_val (model_screen_time_per_day, diff_days, new_val);
     352                 :             :     }
     353                 :             : 
     354                 :           0 :   element = &g_array_index (model_screen_time_per_day, double, diff_days);
     355                 :           0 :   *element += duration_secs / 60.0;
     356                 :           0 : }
     357                 :             : 
     358                 :             : static gboolean
     359                 :           0 : mct_screen_time_statistics_row_load_data_finish (CcScreenTimeStatisticsRow  *screen_time_statistics_row,
     360                 :             :                                                  GAsyncResult               *result,
     361                 :             :                                                  GDate                      *out_new_model_start_date,
     362                 :             :                                                  size_t                     *out_new_model_n_days,
     363                 :             :                                                  double                    **out_new_model_screen_time_per_day,
     364                 :             :                                                  GError                    **error)
     365                 :             : {
     366                 :           0 :   g_autoptr(LoadDataData) data = NULL;
     367                 :             : 
     368                 :           0 :   g_return_val_if_fail (g_task_is_valid (result, screen_time_statistics_row), FALSE);
     369                 :             : 
     370                 :             :   /* Set up in case of error. */
     371         [ #  # ]:           0 :   if (out_new_model_start_date != NULL)
     372                 :           0 :     g_date_clear (out_new_model_start_date, 1);
     373         [ #  # ]:           0 :   if (out_new_model_n_days != NULL)
     374                 :           0 :     *out_new_model_n_days = 0;
     375         [ #  # ]:           0 :   if (out_new_model_screen_time_per_day != NULL)
     376                 :           0 :     *out_new_model_screen_time_per_day = NULL;
     377                 :             : 
     378                 :           0 :   data = g_task_propagate_pointer (G_TASK (result), error);
     379                 :             : 
     380         [ #  # ]:           0 :   if (data == NULL)
     381                 :           0 :     return FALSE;
     382                 :             : 
     383                 :             :   /* Success! */
     384         [ #  # ]:           0 :   if (out_new_model_start_date != NULL)
     385                 :           0 :     *out_new_model_start_date = *data->start_date;
     386         [ #  # ]:           0 :   if (out_new_model_n_days != NULL)
     387                 :           0 :     *out_new_model_n_days = data->n_days;
     388         [ #  # ]:           0 :   if (out_new_model_screen_time_per_day != NULL)
     389                 :           0 :     *out_new_model_screen_time_per_day = g_steal_pointer (&data->screen_time_per_day);
     390                 :             : 
     391                 :           0 :   return TRUE;
     392                 :             : }
     393                 :             : 
     394                 :             : static void
     395                 :           0 : mct_screen_time_statistics_row_class_init (MctScreenTimeStatisticsRowClass *klass)
     396                 :             : {
     397                 :           0 :   GObjectClass *object_class = G_OBJECT_CLASS (klass);
     398                 :           0 :   CcScreenTimeStatisticsRowClass *screen_time_statistics_row_class = CC_SCREEN_TIME_STATISTICS_ROW_CLASS (klass);
     399                 :             : 
     400                 :           0 :   object_class->get_property = mct_screen_time_statistics_row_get_property;
     401                 :           0 :   object_class->set_property = mct_screen_time_statistics_row_set_property;
     402                 :           0 :   object_class->constructed = mct_screen_time_statistics_row_constructed;
     403                 :           0 :   object_class->dispose = mct_screen_time_statistics_row_dispose;
     404                 :             : 
     405                 :           0 :   screen_time_statistics_row_class->load_data_async = mct_screen_time_statistics_row_load_data_async;
     406                 :           0 :   screen_time_statistics_row_class->load_data_finish = mct_screen_time_statistics_row_load_data_finish;
     407                 :             : 
     408                 :             :   /**
     409                 :             :    * MctScreenTimeStatisticsRow:connection: (not nullable)
     410                 :             :    *
     411                 :             :    * A connection to the system bus, where malcontent-timerd runs. It’s
     412                 :             :    * provided to allow an existing connection to be re-used and for testing
     413                 :             :    * purposes.
     414                 :             :    *
     415                 :             :    * Since 0.14.0
     416                 :             :    */
     417                 :           0 :   properties[PROP_CONNECTION] = g_param_spec_object ("connection", NULL, NULL,
     418                 :             :                                                      G_TYPE_DBUS_CONNECTION,
     419                 :             :                                                      G_PARAM_READWRITE |
     420                 :             :                                                      G_PARAM_CONSTRUCT_ONLY |
     421                 :             :                                                      G_PARAM_STATIC_STRINGS);
     422                 :             : 
     423                 :             :   /**
     424                 :             :    * MctScreenTimeStatisticsRow:uid:
     425                 :             :    *
     426                 :             :    * The selected user’s UID.
     427                 :             :    *
     428                 :             :    * Since 0.14.0
     429                 :             :    */
     430                 :           0 :   properties[PROP_UID] = g_param_spec_uint ("uid", NULL, NULL,
     431                 :             :                                             0, G_MAXUINT, 0,
     432                 :             :                                             G_PARAM_READWRITE |
     433                 :             :                                             G_PARAM_CONSTRUCT_ONLY |
     434                 :             :                                             G_PARAM_STATIC_STRINGS);
     435                 :             : 
     436                 :           0 :   g_object_class_install_properties (object_class, G_N_ELEMENTS (properties), properties);
     437                 :           0 : }
     438                 :             : 
     439                 :             : static void
     440                 :           0 : mct_screen_time_statistics_row_init (MctScreenTimeStatisticsRow *self)
     441                 :             : {
     442                 :           0 : }
     443                 :             : 
     444                 :             : /**
     445                 :             :  * mct_screen_time_statistics_row_new:
     446                 :             :  * @connection: (transfer none): a #GDBusConnection to use
     447                 :             :  * @uid: user ID to use
     448                 :             :  *
     449                 :             :  * Create a new #MctScreenTimeStatisticsRow widget.
     450                 :             :  *
     451                 :             :  * Returns: (transfer full): a new screen time statistics row
     452                 :             :  * Since: 0.14.0
     453                 :             :  */
     454                 :             : MctScreenTimeStatisticsRow *
     455                 :           0 : mct_screen_time_statistics_row_new (GDBusConnection *connection,
     456                 :             :                                     uid_t            uid)
     457                 :             : {
     458                 :           0 :   g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
     459                 :             : 
     460                 :           0 :   return g_object_new (MCT_TYPE_SCREEN_TIME_STATISTICS_ROW,
     461                 :             :                        "connection", connection,
     462                 :             :                        "uid", uid,
     463                 :             :                        NULL);
     464                 :             : }
        

Generated by: LCOV version 2.0-1