LCOV - code coverage report
Current view: top level - malcontent-control - cc-time-row.c (source / functions) Coverage Total Hit
Test: 2 coverage DB files Lines: 0.0 % 113 0
Test Date: 2025-09-15 13:55:46 Functions: 0.0 % 19 0
Branches: 0.0 % 22 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                 :             :  * This library is free software; you can redistribute it and/or
       6                 :             :  * modify it under the terms of the GNU Lesser General Public
       7                 :             :  * License as published by the Free Software Foundation; either
       8                 :             :  * version 2 of the License, or (at your option) any later version.
       9                 :             :  *
      10                 :             :  * This library is distributed in the hope that it will be useful,
      11                 :             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      12                 :             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13                 :             :  * Lesser General Public License for more details.
      14                 :             :  *
      15                 :             :  * You should have received a copy of the GNU Lesser General
      16                 :             :  * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
      17                 :             :  *
      18                 :             :  * Authors:
      19                 :             :  *  - Ignacy KuchciƄski <ignacykuchcinski@gnome.org>
      20                 :             :  *
      21                 :             :  * SPDX-License-Identifier: GPL-3.0-or-later
      22                 :             :  */
      23                 :             : #include "config.h"
      24                 :             : #include <glib/gi18n.h>
      25                 :             : 
      26                 :             : #define GNOME_DESKTOP_USE_UNSTABLE_API
      27                 :             : #include <libgnome-desktop/gnome-wall-clock.h>
      28                 :             : #include <adwaita.h>
      29                 :             : #include <glib-object.h>
      30                 :             : #include <gtk/gtk.h>
      31                 :             : 
      32                 :             : #include "cc-time-editor.h"
      33                 :             : #include "cc-time-row.h"
      34                 :             : 
      35                 :             : #define CLOCK_SCHEMA "org.gnome.desktop.interface"
      36                 :             : #define CLOCK_FORMAT_KEY "clock-format"
      37                 :             : 
      38                 :             : /**
      39                 :             :  * CcTimeRow:
      40                 :             :  *
      41                 :             :  * An #AdwActionRow used to enter a time, represented as time string.
      42                 :             :  *
      43                 :             :  * The currently specified time is shown in a label. If the row is activated
      44                 :             :  * a popover is shown containing a #CcTimeEditor to edit the time.
      45                 :             :  */
      46                 :             : struct _CcTimeRow {
      47                 :             :   AdwActionRow parent_instance;
      48                 :             : 
      49                 :             :   GtkWidget *arrow_box;
      50                 :             :   GtkLabel *current;
      51                 :             :   GtkPopover *popover;
      52                 :             :   CcTimeEditor *editor;
      53                 :             :   GSettings *clock_settings;
      54                 :             : };
      55                 :             : 
      56   [ #  #  #  #  :           0 : G_DEFINE_TYPE (CcTimeRow, cc_time_row, ADW_TYPE_ACTION_ROW)
                   #  # ]
      57                 :             : 
      58                 :             : typedef enum {
      59                 :             :   PROP_TIME = 1,
      60                 :             : } CcTimeRowProperty;
      61                 :             : 
      62                 :             : static GParamSpec *props[PROP_TIME + 1];
      63                 :             : 
      64                 :             : static void cc_time_row_get_property (GObject    *object,
      65                 :             :                                       guint       property_id,
      66                 :             :                                       GValue     *value,
      67                 :             :                                       GParamSpec *pspec);
      68                 :             : static void cc_time_row_set_property (GObject      *object,
      69                 :             :                                       guint         property_id,
      70                 :             :                                       const GValue *value,
      71                 :             :                                       GParamSpec   *pspec);
      72                 :             : static void cc_time_row_dispose (GObject *object);
      73                 :             : static void cc_time_row_finalize (GObject *object);
      74                 :             : static void cc_time_row_size_allocate (GtkWidget *widget,
      75                 :             :                                        int        width,
      76                 :             :                                        int        height,
      77                 :             :                                        int        baseline);
      78                 :             : static gboolean cc_time_row_focus (GtkWidget        *widget,
      79                 :             :                                        GtkDirectionType  direction);
      80                 :             : static void cc_time_row_activate (AdwActionRow *row);
      81                 :             : static void popover_notify_visible_cb (GObject    *object,
      82                 :             :                                        GParamSpec *pspec,
      83                 :             :                                        gpointer    user_data);
      84                 :             : static void update_current_label (CcTimeRow *self);
      85                 :             : static void editor_time_changed_cb (CcTimeEditor *editor,
      86                 :             :                                     gpointer      user_data);
      87                 :             : static void time_row_clock_changed_cb (CcTimeRow *self);
      88                 :             : 
      89                 :             : static void
      90                 :           0 : cc_time_row_class_init (CcTimeRowClass *klass)
      91                 :             : {
      92                 :           0 :   GObjectClass *object_class = G_OBJECT_CLASS (klass);
      93                 :           0 :   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
      94                 :           0 :   AdwActionRowClass *row_class = ADW_ACTION_ROW_CLASS (klass);
      95                 :             : 
      96                 :           0 :   object_class->get_property = cc_time_row_get_property;
      97                 :           0 :   object_class->set_property = cc_time_row_set_property;
      98                 :           0 :   object_class->dispose = cc_time_row_dispose;
      99                 :           0 :   object_class->finalize = cc_time_row_finalize;
     100                 :             : 
     101                 :           0 :   widget_class->size_allocate = cc_time_row_size_allocate;
     102                 :           0 :   widget_class->focus = cc_time_row_focus;
     103                 :             : 
     104                 :           0 :   row_class->activate = cc_time_row_activate;
     105                 :             : 
     106                 :             :   /**
     107                 :             :    * CcTimeRow:time:
     108                 :             :    *
     109                 :             :    * Time displayed in the row or chosen in the editor,
     110                 :             :    * in seconds since midnight.
     111                 :             :    */
     112                 :           0 :   props[PROP_TIME] =
     113                 :           0 :     g_param_spec_uint ("time",
     114                 :             :                        NULL, NULL,
     115                 :             :                        0, G_MAXUINT, 0,
     116                 :             :                        G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
     117                 :             : 
     118                 :           0 :   g_object_class_install_properties (object_class, G_N_ELEMENTS (props), props);
     119                 :             : 
     120                 :           0 :   g_type_ensure (CC_TYPE_TIME_EDITOR);
     121                 :             : 
     122                 :           0 :   gtk_widget_class_set_template_from_resource (widget_class, "/org/freedesktop/MalcontentControl/ui/cc-time-row.ui");
     123                 :             : 
     124                 :           0 :   gtk_widget_class_bind_template_child (widget_class, CcTimeRow, current);
     125                 :           0 :   gtk_widget_class_bind_template_child (widget_class, CcTimeRow, arrow_box);
     126                 :           0 :   gtk_widget_class_bind_template_child (widget_class, CcTimeRow, editor);
     127                 :           0 :   gtk_widget_class_bind_template_child (widget_class, CcTimeRow, popover);
     128                 :           0 :   gtk_widget_class_bind_template_callback (widget_class, popover_notify_visible_cb);
     129                 :           0 :   gtk_widget_class_bind_template_callback (widget_class, editor_time_changed_cb);
     130                 :             : 
     131                 :           0 :   gtk_widget_class_set_accessible_role (widget_class, GTK_ACCESSIBLE_ROLE_COMBO_BOX);
     132                 :           0 : }
     133                 :             : 
     134                 :             : static void
     135                 :           0 : cc_time_row_init (CcTimeRow *self)
     136                 :             : {
     137                 :           0 :   gtk_widget_init_template (GTK_WIDGET (self));
     138                 :             : 
     139                 :           0 :   self->clock_settings = g_settings_new (CLOCK_SCHEMA);
     140                 :             : 
     141                 :           0 :   g_signal_connect_object (self->clock_settings, "changed::" CLOCK_FORMAT_KEY,
     142                 :             :                            G_CALLBACK (time_row_clock_changed_cb), self,
     143                 :             :                            G_CONNECT_SWAPPED);
     144                 :             : 
     145                 :           0 :   update_current_label (self);
     146                 :           0 : }
     147                 :             : 
     148                 :             : static void
     149                 :           0 : cc_time_row_get_property (GObject    *object,
     150                 :             :                           guint       property_id,
     151                 :             :                           GValue     *value,
     152                 :             :                           GParamSpec *pspec)
     153                 :             : {
     154                 :           0 :   CcTimeRow *self = CC_TIME_ROW (object);
     155                 :             : 
     156         [ #  # ]:           0 :   switch ((CcTimeRowProperty) property_id)
     157                 :             :     {
     158                 :           0 :     case PROP_TIME:
     159                 :           0 :       g_value_set_uint (value, cc_time_row_get_time (self));
     160                 :           0 :       break;
     161                 :           0 :     default:
     162                 :           0 :       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
     163                 :           0 :       break;
     164                 :             :     }
     165                 :           0 : }
     166                 :             : 
     167                 :             : static void
     168                 :           0 : cc_time_row_set_property (GObject      *object,
     169                 :             :                           guint         property_id,
     170                 :             :                           const GValue *value,
     171                 :             :                           GParamSpec   *pspec)
     172                 :             : {
     173                 :           0 :   CcTimeRow *self = CC_TIME_ROW (object);
     174                 :             : 
     175         [ #  # ]:           0 :   switch ((CcTimeRowProperty) property_id)
     176                 :             :     {
     177                 :           0 :     case PROP_TIME:
     178                 :           0 :       cc_time_row_set_time (self, g_value_get_uint (value));
     179                 :           0 :       break;
     180                 :           0 :     default:
     181                 :           0 :       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
     182                 :             :     }
     183                 :           0 : }
     184                 :             : 
     185                 :             : static void
     186                 :           0 : cc_time_row_dispose (GObject *object)
     187                 :             : {
     188                 :           0 :   gtk_widget_dispose_template (GTK_WIDGET (object), CC_TYPE_TIME_ROW);
     189                 :             : 
     190                 :           0 :   G_OBJECT_CLASS (cc_time_row_parent_class)->dispose (object);
     191                 :           0 : }
     192                 :             : 
     193                 :             : static void
     194                 :           0 : cc_time_row_finalize (GObject *object)
     195                 :             : {
     196                 :           0 :   CcTimeRow *self = CC_TIME_ROW (object);
     197                 :             : 
     198         [ #  # ]:           0 :   g_clear_object (&self->clock_settings);
     199                 :             : 
     200                 :           0 :   G_OBJECT_CLASS (cc_time_row_parent_class)->finalize (object);
     201                 :           0 : }
     202                 :             : 
     203                 :             : static void
     204                 :           0 : cc_time_row_size_allocate (GtkWidget *widget,
     205                 :             :                            int        width,
     206                 :             :                            int        height,
     207                 :             :                            int        baseline)
     208                 :             : {
     209                 :           0 :   CcTimeRow *self = CC_TIME_ROW (widget);
     210                 :             : 
     211                 :           0 :   GTK_WIDGET_CLASS (cc_time_row_parent_class)->size_allocate (widget, width, height, baseline);
     212                 :             : 
     213                 :           0 :   gtk_popover_present (self->popover);
     214                 :           0 : }
     215                 :             : 
     216                 :             : static gboolean
     217                 :           0 : cc_time_row_focus (GtkWidget        *widget,
     218                 :             :                    GtkDirectionType  direction)
     219                 :             : {
     220                 :           0 :   CcTimeRow *self = CC_TIME_ROW (widget);
     221                 :             : 
     222   [ #  #  #  # ]:           0 :   if (self->popover != NULL && gtk_widget_get_visible (GTK_WIDGET (self->popover)))
     223                 :           0 :     return gtk_widget_child_focus (GTK_WIDGET (self->popover), direction);
     224                 :             :   else
     225                 :           0 :     return GTK_WIDGET_CLASS (cc_time_row_parent_class)->focus (widget, direction);
     226                 :             : }
     227                 :             : 
     228                 :             : static void
     229                 :           0 : cc_time_row_activate (AdwActionRow *row)
     230                 :             : {
     231                 :           0 :   CcTimeRow *self = CC_TIME_ROW (row);
     232                 :             : 
     233         [ #  # ]:           0 :   if (gtk_widget_get_visible (self->arrow_box))
     234                 :           0 :     gtk_popover_popup (self->popover);
     235                 :           0 : }
     236                 :             : 
     237                 :             : static void
     238                 :           0 : popover_notify_visible_cb (GObject    *object,
     239                 :             :                            GParamSpec *pspec,
     240                 :             :                            gpointer    user_data)
     241                 :             : {
     242                 :           0 :   CcTimeRow *self = CC_TIME_ROW (user_data);
     243                 :             : 
     244         [ #  # ]:           0 :   if (gtk_widget_get_visible (GTK_WIDGET (self->popover)))
     245                 :           0 :     gtk_widget_add_css_class (GTK_WIDGET (self), "has-open-popup");
     246                 :             :   else
     247                 :           0 :     gtk_widget_remove_css_class (GTK_WIDGET (self), "has-open-popup");
     248                 :           0 : }
     249                 :             : 
     250                 :             : static void
     251                 :           0 : update_current_label (CcTimeRow *self)
     252                 :             : {
     253                 :             :   GDesktopClockFormat clock_format;
     254                 :           0 :   g_autofree char *time_str = NULL;
     255                 :           0 :   g_autoptr (GDateTime) date_time = NULL;
     256                 :             : 
     257                 :           0 :   clock_format = g_settings_get_enum (self->clock_settings, CLOCK_FORMAT_KEY);
     258                 :           0 :   guint hours = cc_time_editor_get_hour (self->editor);
     259                 :           0 :   guint minutes = cc_time_editor_get_minute (self->editor);
     260                 :             : 
     261                 :           0 :   date_time = g_date_time_new_utc (1, 1, 1, hours % 24, minutes, 0);
     262                 :             :   
     263         [ #  # ]:           0 :   if (clock_format == G_DESKTOP_CLOCK_FORMAT_12H)
     264                 :             :     {
     265                 :             :       /* Translators: This is time format used in 12-hour mode. */
     266                 :           0 :       time_str = g_date_time_format (date_time, _("%-l:%M %p"));
     267                 :             :     }
     268                 :             :   else
     269                 :             :     {
     270                 :             :       /* Translators: This is time format used in 24-hour mode. */
     271                 :           0 :       time_str = g_date_time_format (date_time, _("%-k:%M"));
     272                 :             :     }
     273                 :             : 
     274                 :           0 :   gtk_label_set_label (self->current, time_str);
     275                 :           0 : }
     276                 :             : 
     277                 :             : static void
     278                 :           0 : editor_time_changed_cb (CcTimeEditor *editor,
     279                 :             :                         gpointer      user_data)
     280                 :             : {
     281                 :           0 :   CcTimeRow *self = CC_TIME_ROW (user_data);
     282                 :             : 
     283                 :           0 :   update_current_label (self);
     284                 :             : 
     285                 :           0 :   g_object_notify_by_pspec (G_OBJECT (self), props[PROP_TIME]);
     286                 :           0 : }
     287                 :             : 
     288                 :             : static void
     289                 :           0 : time_row_clock_changed_cb (CcTimeRow *self)
     290                 :             : {
     291                 :           0 :   update_current_label (self);
     292                 :           0 : }
     293                 :             : 
     294                 :             : /**
     295                 :             :  * cc_time_row_new:
     296                 :             :  *
     297                 :             :  * Create a new #CcTimeRow.
     298                 :             :  *
     299                 :             :  * Returns: (transfer full): the new #CcTimeRow
     300                 :             :  */
     301                 :             : CcTimeRow *
     302                 :           0 : cc_time_row_new (void)
     303                 :             : {
     304                 :           0 :   return g_object_new (CC_TYPE_TIME_ROW, NULL);
     305                 :             : }
     306                 :             : 
     307                 :             : /**
     308                 :             :  * cc_time_row_get_time:
     309                 :             :  * @self: a #CcTimeRow
     310                 :             :  *
     311                 :             :  * Get the value of #CcTimeRow:time.
     312                 :             :  *
     313                 :             :  * Returns: number of minutes since midnight currently specified by the row
     314                 :             :  */
     315                 :             : guint
     316                 :           0 : cc_time_row_get_time (CcTimeRow *self)
     317                 :             : {
     318                 :           0 :   g_return_val_if_fail (CC_IS_TIME_ROW (self), 0);
     319                 :             : 
     320                 :           0 :   guint hours = cc_time_editor_get_hour (self->editor);
     321                 :           0 :   guint minutes = cc_time_editor_get_minute (self->editor);
     322                 :             : 
     323                 :           0 :   return hours * 60 + minutes;
     324                 :             : }
     325                 :             : 
     326                 :             : /**
     327                 :             :  * cc_time_row_set_time:
     328                 :             :  * @self: a #CcTimeRow
     329                 :             :  * @time: the time, in minutes since midnight
     330                 :             :  *
     331                 :             :  * Set the value of #CcTimeRow:time.
     332                 :             :  */
     333                 :             : void
     334                 :           0 : cc_time_row_set_time (CcTimeRow *self,
     335                 :             :                       guint      time)
     336                 :             : {
     337                 :           0 :   g_return_if_fail (CC_IS_TIME_ROW (self));
     338                 :             : 
     339                 :             :   guint hours, minutes;
     340                 :             : 
     341                 :           0 :   hours = time / 60;
     342                 :           0 :   minutes = time % 60;
     343                 :             : 
     344                 :           0 :   cc_time_editor_set_time (self->editor, hours, minutes);
     345                 :             : 
     346                 :           0 :   g_object_notify_by_pspec (G_OBJECT (self), props[PROP_TIME]);
     347                 :             : }
        

Generated by: LCOV version 2.0-1