diff --git a/panels/common/cc-number-list.h b/panels/common/cc-number-list.h deleted file mode 100644 index 59f4935b415531cd11baa034eb7eb78d67d90b04..0000000000000000000000000000000000000000 --- a/panels/common/cc-number-list.h +++ /dev/null @@ -1,67 +0,0 @@ -/* cc-number-list.h - * - * Copyright 2024 Matthijs Velsink - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -#pragma once - -#include - -G_BEGIN_DECLS - - -/** - * CcNumberOrder: - * @CC_NUMBER_ORDER_FIRST: place number first in the list - * @CC_NUMBER_ORDER_DEFAULT: use the `sort-type` of the list - * @CC_NUMBER_ORDER_LAST: place number last in the list - * - * Defines a special, fixed ordering of a `CcNumberObject` inside a - * `CcNumberList`. - */ -typedef enum -{ - CC_NUMBER_ORDER_FIRST, - CC_NUMBER_ORDER_DEFAULT, - CC_NUMBER_ORDER_LAST -} CcNumberOrder; - -#define CC_TYPE_NUMBER_OBJECT (cc_number_object_get_type()) -G_DECLARE_FINAL_TYPE (CcNumberObject, cc_number_object, CC, NUMBER_OBJECT, GObject) - -CcNumberObject *cc_number_object_new (int value); -CcNumberObject *cc_number_object_new_full (int value, const char *string, CcNumberOrder order); - -int cc_number_object_get_value (CcNumberObject *self); -const char* cc_number_object_get_string (CcNumberObject *self); -CcNumberOrder cc_number_object_get_order (CcNumberObject *self); - -char *cc_number_object_to_string_for_seconds (CcNumberObject *self); -char *cc_number_object_to_string_for_minutes (CcNumberObject *self); - -#define CC_TYPE_NUMBER_LIST (cc_number_list_get_type()) -G_DECLARE_FINAL_TYPE (CcNumberList, cc_number_list, CC, NUMBER_LIST, GObject) - -CcNumberList *cc_number_list_new (GtkSortType sort_type); - -guint cc_number_list_add_value (CcNumberList *self, int value); -guint cc_number_list_add_value_full (CcNumberList *self, int value, const char *string, CcNumberOrder order); -int cc_number_list_get_value (CcNumberList *self, guint position); -gboolean cc_number_list_has_value (CcNumberList *self, int value, guint *position); - -G_END_DECLS diff --git a/panels/common/cc-number-list.c b/panels/common/cc-number-row.c similarity index 53% rename from panels/common/cc-number-list.c rename to panels/common/cc-number-row.c index a600e69355faf687edbd863dab32e8f245d66187..404c0a07b460a1c290707c35b80765165189e676 100644 --- a/panels/common/cc-number-list.c +++ b/panels/common/cc-number-row.c @@ -1,4 +1,4 @@ -/* cc-number-list.c +/* cc-number-row.c * * Copyright 2024 Matthijs Velsink * @@ -19,10 +19,10 @@ */ #undef G_LOG_DOMAIN -#define G_LOG_DOMAIN "cc-number-list" +#define G_LOG_DOMAIN "cc-number-row" -#include "cc-number-list.h" -#include "cc-number-list-enums.h" +#include "cc-number-row.h" +#include "cc-number-row-enums.h" #include "cc-util.h" /** @@ -141,7 +141,7 @@ cc_number_object_class_init (CcNumberObjectClass *klass) /** * CcNumberObject:order: (attributes org.gtk.Property.get=cc_number_object_get_order) * - * The (optional) fixed ordering of the `CcNumberObject` inside a `CcNumberList`. + * The (optional) fixed ordering of the `CcNumberObject` inside a `CcNumberRow` list. */ obj_props[OBJ_PROP_ORDER] = g_param_spec_enum ("order", NULL, NULL, @@ -213,21 +213,21 @@ cc_number_object_get_value (CcNumberObject *self) * * Gets the fixed string representation of the stored value. * - * Returns: (nullable): the fixed string representation + * Returns: (transfer full) (nullable): the fixed string representation */ -const char* +char* cc_number_object_get_string (CcNumberObject *self) { g_return_val_if_fail (CC_IS_NUMBER_OBJECT (self), NULL); - return self->string; + return g_strdup (self->string); } /** * cc_number_object_get_order: * @self: a `CcNumberObject` * - * Gets the fixed orderering of @self inside a `CcNumberList`. + * Gets the fixed orderering of @self inside a `CcNumberRow` list. * * Returns: (nullable): the fixed orderering */ @@ -239,112 +239,68 @@ cc_number_object_get_order (CcNumberObject *self) return self->order; } -/** - * cc_number_object_to_string_for_seconds: - * @self: a `CcNumberObject` - * - * Gets the string representation of @self, assuming the stored value is - * a number of seconds. If @self has the special `string` set, that is - * returned instead. - * - * This function is useful in expressions. - * - * Returns: (transfer full): the resulting string - */ -char * +#define MILLIS_PER_SEC (1000) +#define MILLIS_PER_MIN (60 * MILLIS_PER_SEC) +#define MILLIS_PER_HOUR (60 * MILLIS_PER_MIN) + +static char * cc_number_object_to_string_for_seconds (CcNumberObject *self) { if (self->string) return g_strdup (self->string); - return cc_util_time_to_string_text ((gint64) 1000 * self->value); + return cc_util_time_to_string_text ((gint64) MILLIS_PER_SEC * self->value); } -/** - * cc_number_object_to_string_for_minutes: - * @self: a `CcNumberObject` - * - * Gets the string representation of @self, assuming the stored value is - * a number of minutes. If @self has the special `string` set, that is - * returned instead. - * - * This function is useful in expressions. - * - * Returns: (transfer full): the resulting string - */ -char * +static char * cc_number_object_to_string_for_minutes (CcNumberObject *self) { if (self->string) return g_strdup (self->string); - return cc_util_time_to_string_text ((gint64) 1000 * 60 * self->value); + return cc_util_time_to_string_text ((gint64) MILLIS_PER_MIN * self->value); +} + +static char * +cc_number_object_to_string_for_hours (CcNumberObject *self) +{ + if (self->string) + return g_strdup (self->string); + + return cc_util_time_to_string_text ((gint64) MILLIS_PER_HOUR * self->value); } /** - * CcNumberList: + * CcNumberRow: * - * `CcNumberList` is a simple list model that wraps a GListStore of + * `CcNumberRow` is an `AdwComboRow` with a model that wraps a GListStore of * `CcStringObject`. It has convenient methods to add values directly. */ -struct _CcNumberList { - GObject parent_instance; +struct _CcNumberRow { + AdwComboRow parent_instance; - GListStore *store; - GtkSortType sort_type; + GListStore *store; + CcNumberValueType value_type; + CcNumberSortType sort_type; }; -static GType -cc_number_list_get_item_type (GListModel *list) -{ - CcNumberList *self = CC_NUMBER_LIST (list); - - return g_list_model_get_item_type (G_LIST_MODEL (self->store)); -} - -static guint -cc_number_list_get_n_items (GListModel *list) -{ - CcNumberList *self = CC_NUMBER_LIST (list); - - return g_list_model_get_n_items (G_LIST_MODEL (self->store)); -} - -static gpointer -cc_number_list_get_item (GListModel *list, - guint position) -{ - CcNumberList *self = CC_NUMBER_LIST (list); - - return g_list_model_get_item (G_LIST_MODEL (self->store), position); -} - -static void -cc_number_list_model_init (GListModelInterface *iface) -{ - iface->get_item_type = cc_number_list_get_item_type; - iface->get_n_items = cc_number_list_get_n_items; - iface->get_item = cc_number_list_get_item; -} - -G_DEFINE_TYPE_WITH_CODE (CcNumberList, cc_number_list, G_TYPE_OBJECT, - G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL, - cc_number_list_model_init)) +G_DEFINE_TYPE(CcNumberRow, cc_number_row, ADW_TYPE_COMBO_ROW) enum { - LST_PROP_0, - LST_PROP_SORT_TYPE, - LST_PROP_VALUES, - LST_PROP_SPECIAL_VALUE, - LST_N_PROPS + ROW_PROP_0, + ROW_PROP_VALUE_TYPE, + ROW_PROP_SORT_TYPE, + ROW_PROP_VALUES, + ROW_PROP_SPECIAL_VALUE, + ROW_N_PROPS }; -static GParamSpec *lst_props[LST_N_PROPS]; +static GParamSpec *row_props[ROW_N_PROPS]; static void -cc_number_list_add_values_from_variant (CcNumberList *self, - GVariant *variant) +cc_number_row_add_values_from_variant (CcNumberRow *self, + GVariant *variant) { const int *values; gsize n_elements, i; @@ -365,22 +321,25 @@ cc_number_list_add_values_from_variant (CcNumberList *self, } static void -cc_number_list_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) +cc_number_row_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) { - CcNumberList *self = CC_NUMBER_LIST (object); + CcNumberRow *self = CC_NUMBER_ROW (object); CcNumberObject *number; switch (prop_id) { - case LST_PROP_SORT_TYPE: + case ROW_PROP_VALUE_TYPE: + self->value_type = g_value_get_enum (value); + break; + case ROW_PROP_SORT_TYPE: self->sort_type = g_value_get_enum (value); break; - case LST_PROP_VALUES: - cc_number_list_add_values_from_variant (self, g_value_get_variant (value)); + case ROW_PROP_VALUES: + cc_number_row_add_values_from_variant (self, g_value_get_variant (value)); break; - case LST_PROP_SPECIAL_VALUE: + case ROW_PROP_SPECIAL_VALUE: /* Construct-only property, so check for NULL, as NULL is passed if not provided */ number = g_value_get_object (value); if (number) @@ -394,7 +353,7 @@ cc_number_list_set_property (GObject *object, static int compare_numbers (CcNumberObject *number_a, CcNumberObject *number_b, - CcNumberList *self) + CcNumberRow *self) { /* Handle special order first (works because of the ordering of CcNumberOrder) */ if (number_a->order != CC_NUMBER_ORDER_DEFAULT || @@ -402,110 +361,156 @@ compare_numbers (CcNumberObject *number_a, return number_a->order - number_b->order; /* Otherwise normal value comparison */ - if (self->sort_type == GTK_SORT_ASCENDING) + if (self->sort_type == CC_NUMBER_SORT_ASCENDING) return number_a->value - number_b->value; - else + else if (self->sort_type == CC_NUMBER_SORT_DESCENDING) return number_b->value - number_a->value; + else + return 0; } static void -cc_number_list_constructed (GObject *obj) +cc_number_row_constructed (GObject *obj) { - CcNumberList *self = CC_NUMBER_LIST (obj); + CcNumberRow *self = CC_NUMBER_ROW (obj); /* Sort now, as construct-only values could be added before sort-type was changed */ g_list_store_sort (self->store, (GCompareDataFunc) compare_numbers, self); - G_OBJECT_CLASS (cc_number_list_parent_class)->constructed (obj); + /* Only now add it as a model */ + adw_combo_row_set_model (ADW_COMBO_ROW (self), G_LIST_MODEL (self->store)); + + /* And set the expression based on the value-type */ + if (self->value_type != CC_NUMBER_VALUE_CUSTOM) { + char * (*number_to_string_func)(CcNumberObject *); + g_autoptr(GtkExpression) expression = NULL; + + switch (self->value_type) { + case CC_NUMBER_VALUE_STRING: + number_to_string_func = cc_number_object_get_string; + break; + case CC_NUMBER_VALUE_SECONDS: + number_to_string_func = cc_number_object_to_string_for_seconds; + break; + case CC_NUMBER_VALUE_MINUTES: + number_to_string_func = cc_number_object_to_string_for_minutes; + break; + case CC_NUMBER_VALUE_HOURS: + number_to_string_func = cc_number_object_to_string_for_hours; + break; + default: + g_assert_not_reached (); + } + + expression = gtk_cclosure_expression_new (G_TYPE_STRING, NULL, + 0, NULL, + G_CALLBACK (number_to_string_func), + NULL, NULL); + adw_combo_row_set_expression (ADW_COMBO_ROW (self), expression); + } + + G_OBJECT_CLASS (cc_number_row_parent_class)->constructed (obj); } static void -cc_number_list_dispose (GObject *object) +cc_number_row_dispose (GObject *object) { - CcNumberList *self = CC_NUMBER_LIST (object); + CcNumberRow *self = CC_NUMBER_ROW (object); g_clear_object (&self->store); - G_OBJECT_CLASS (cc_number_list_parent_class)->dispose (object); + G_OBJECT_CLASS (cc_number_row_parent_class)->dispose (object); } static void -cc_number_list_class_init (CcNumberListClass *klass) +cc_number_row_class_init (CcNumberRowClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); g_autoptr(GVariantType) values_type = NULL; - object_class->constructed = cc_number_list_constructed; - object_class->dispose = cc_number_list_dispose; - object_class->set_property = cc_number_list_set_property; + object_class->constructed = cc_number_row_constructed; + object_class->dispose = cc_number_row_dispose; + object_class->set_property = cc_number_row_set_property; + + /** + * CcNumberRow:value-type: + * + * The interpretation of the values in the list of the row. Determines what + * strings will be generated to represent the value in the list. The + * `string` property of a number will always take priority if it is set. + * Sets the `expression` property of the underlying AdwComboRow, unless the + * value type is `CC_NUMBER_VALUE_CUSTOM`. + */ + row_props[ROW_PROP_VALUE_TYPE] = + g_param_spec_enum ("value-type", NULL, NULL, + CC_TYPE_NUMBER_VALUE_TYPE, CC_NUMBER_VALUE_CUSTOM, + G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); /** - * CcNumberList:sort-type: + * CcNumberRow:sort-type: * - * The sorting of the numbers in the list. + * The sorting of the numbers in the list of the row. */ - lst_props[LST_PROP_SORT_TYPE] = + row_props[ROW_PROP_SORT_TYPE] = g_param_spec_enum ("sort-type", NULL, NULL, - GTK_TYPE_SORT_TYPE, GTK_SORT_ASCENDING, + CC_TYPE_NUMBER_SORT_TYPE, CC_NUMBER_SORT_ASCENDING, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); /** - * CcNumberList:values: + * CcNumberRow:values: * * A variant array of integer values. Mainly useful in .ui files, where it * allows for convenient array notation like [num1, num2, num3, ...]. */ values_type = g_variant_type_new_array (G_VARIANT_TYPE_INT32); - lst_props[LST_PROP_VALUES] = + row_props[ROW_PROP_VALUES] = g_param_spec_variant ("values", NULL, NULL, values_type, NULL, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); /** - * CcNumberList:special-value: + * CcNumberRow:special-value: * - * One special value to add to the list. Mainly useful in .ui files. - * If more special values are needed, use `cc_number_list_add_value_full()`. + * One special value to add to the list of the row. Mainly useful in .ui files. + * If more special values are needed, use `cc_number_row_add_value_full()`. */ - lst_props[LST_PROP_SPECIAL_VALUE] = + row_props[ROW_PROP_SPECIAL_VALUE] = g_param_spec_object ("special-value", NULL, NULL, CC_TYPE_NUMBER_OBJECT, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); - g_object_class_install_properties (object_class, LST_N_PROPS, lst_props); + g_object_class_install_properties (object_class, ROW_N_PROPS, row_props); } static void -cc_number_list_init (CcNumberList *self) +cc_number_row_init (CcNumberRow *self) { self->store = g_list_store_new (CC_TYPE_NUMBER_OBJECT); - - /* Simply loop the GListModel signal back around to self */ - g_signal_connect_swapped (self->store, "items-changed", - G_CALLBACK (g_list_model_items_changed), self); } /** - * cc_number_list_new: - * @sort_type: the sorting of the numbers in the list + * cc_number_row_new: + * @sort_type: the sorting of the numbers in the list of the row * - * Creates a new `CcNumberList`, with sorting based on @sort_type. + * Creates a new `CcNumberRow`, with sorting based on @sort_type. * - * Returns: the newly created `CcNumberList` + * Returns: the newly created `CcNumberRow` */ -CcNumberList * -cc_number_list_new (GtkSortType sort_type) +CcNumberRow * +cc_number_row_new (CcNumberValueType value_type, + CcNumberSortType sort_type) { - return g_object_new (CC_TYPE_NUMBER_LIST, + return g_object_new (CC_TYPE_NUMBER_ROW, + "value-type", value_type, "sort-type", sort_type, NULL); } static guint -cc_number_list_add_number (CcNumberList *self, - CcNumberObject *number) +cc_number_row_add_number (CcNumberRow *self, + CcNumberObject *number) { - g_return_val_if_fail (CC_IS_NUMBER_LIST (self), 0); + g_return_val_if_fail (CC_IS_NUMBER_ROW (self), 0); g_return_val_if_fail (CC_IS_NUMBER_OBJECT (number), 0); return g_list_store_insert_sorted (self->store, number, @@ -513,11 +518,11 @@ cc_number_list_add_number (CcNumberList *self, } /** - * cc_number_list_add_value: - * @self: a `CcNumberList` - * @value: the value to store in the list + * cc_number_row_add_value: + * @self: a `CcNumberRow` + * @value: the value to store in the list of @self * - * Adds a new `CcNumberObject` based on @value to the list. + * Adds a new `CcNumberObject` based on @value to the list of @self. * The value will be inserted with the correct sorting. * * Also see `cc_number_object_new()`. @@ -525,23 +530,23 @@ cc_number_list_add_number (CcNumberList *self, * Returns: the position in the list where the value got stored */ guint -cc_number_list_add_value (CcNumberList *self, - int value) +cc_number_row_add_value (CcNumberRow *self, + int value) { g_autoptr(CcNumberObject) number = cc_number_object_new (value); - return cc_number_list_add_number (self, number); + return cc_number_row_add_number (self, number); } /** - * cc_number_list_add_value_full: - * @self: a `CcNumberList` - * @value: the value to store in the list + * cc_number_row_add_value_full: + * @self: a `CcNumberRow` + * @value: the value to store in the list of @self * @string: (nullable): the fixed string representation of @value * @order: the fixed ordering of @value * * Adds a new `CcNumberObject` based on @value, @string, and @order to the - * list. + * list of @self. * The value will be inserted with the correct sorting, which takes @order * into account. If two `CcNumberObject`s have the same special @order, their * ordering is based on the order in which they were added to the list. @@ -551,32 +556,32 @@ cc_number_list_add_value (CcNumberList *self, * Returns: the position in the list where the value got stored */ guint -cc_number_list_add_value_full (CcNumberList *self, - int value, - const char *string, - CcNumberOrder order) +cc_number_row_add_value_full (CcNumberRow *self, + int value, + const char *string, + CcNumberOrder order) { g_autoptr(CcNumberObject) number = cc_number_object_new_full (value, string, order); - return cc_number_list_add_number (self, number); + return cc_number_row_add_number (self, number); } /** - * cc_number_list_get_value: - * @self: a `CcNumberList` + * cc_number_row_get_value: + * @self: a `CcNumberRow` * @position: the position of the value to fetch * - * Get the value at @position. + * Get the value at @position in the list of @self. * * Returns: the value at @position */ int -cc_number_list_get_value (CcNumberList *self, - guint position) +cc_number_row_get_value (CcNumberRow *self, + guint position) { g_autoptr(CcNumberObject) number = NULL; - g_return_val_if_fail (CC_IS_NUMBER_LIST (self), -1); + g_return_val_if_fail (CC_IS_NUMBER_ROW (self), -1); number = g_list_model_get_item (G_LIST_MODEL (self->store), position); @@ -597,24 +602,112 @@ equal_numbers (CcNumberObject *number, } /** - * cc_number_list_has_value: - * @self: a `CcNumberList` + * cc_number_row_has_value: + * @self: a `CcNumberRow` * @value: a value * @position: (out) (optional): the first position of @value, if it was found * - * Looks up the given @value in the list. If the value is not found, @position - * will not be set and the return value will be false. + * Looks up the given @value in the list of @self. If the value is not found, + * @position will not be set and the return value will be false. * * Returns: true if the list contains @value, false otherwise */ gboolean -cc_number_list_has_value (CcNumberList *self, - int value, - guint *position) +cc_number_row_has_value (CcNumberRow *self, + int value, + guint *position) { - g_return_val_if_fail (CC_IS_NUMBER_LIST (self), FALSE); + g_return_val_if_fail (CC_IS_NUMBER_ROW (self), FALSE); return g_list_store_find_with_equal_func_full (self->store, NULL, - (GEqualFuncFull) equal_numbers, &value, + (GEqualFuncFull) equal_numbers, &value, position); } + +static gboolean +number_row_settings_get_mapping (GValue *position_value, + GVariant *key_variant, + gpointer user_data) +{ + CcNumberRow *self = CC_NUMBER_ROW (user_data); + int value; + guint position = 0; + + if (g_variant_is_of_type (key_variant, G_VARIANT_TYPE_UINT32)) + if (g_variant_get_uint32 (key_variant) <= INT_MAX) { + value = g_variant_get_uint32 (key_variant); + } else { + g_warning ("Unsigned GSettings value out of range for CcNumberRow"); + position = GTK_INVALID_LIST_POSITION; + } + else + value = g_variant_get_int32 (key_variant); + + if (position != GTK_INVALID_LIST_POSITION) + if (!cc_number_row_has_value (self, value, &position)) + position = cc_number_row_add_value (self, value); + + /* Always set position succesfully, even if invalid, otherwise GSettings will try to map + default values */ + g_value_set_uint (position_value, position); + + return TRUE; +} + +static GVariant * +number_row_settings_set_mapping (const GValue *position_value, + const GVariantType *key_variant_type, + gpointer user_data) +{ + CcNumberRow *self = CC_NUMBER_ROW (user_data); + guint position; + int value; + GVariant *key_variant = NULL; + + position = g_value_get_uint (position_value); + g_return_val_if_fail (position != GTK_INVALID_LIST_POSITION, NULL); + + value = cc_number_row_get_value (self, position); + if (g_variant_type_equal (key_variant_type, G_VARIANT_TYPE_UINT32)) + if (value >= 0) + key_variant = g_variant_new_uint32 (value); + else + g_warning ("Negative CcNumberRow value out of range for unsigned GSettings value"); + else + key_variant = g_variant_new_int32 (value); + + return key_variant; +} + +/** + * cc_number_row_bind_settings: + * @self: a `CcNumberRow` + * @settings: a `GSettings` object + * @key: the key to bind + * + * Creates a binding between the @key in the @settings object, and the + * selected value of @self. The value type of @key must be an (unsigned) + * integer. + * + * If the value of @key does not exist yet in the the list of @self, it + * will be added. + */ +void +cc_number_row_bind_settings (CcNumberRow *self, + GSettings *settings, + const gchar *key) +{ + g_autoptr(GVariant) key_variant = NULL; + + g_return_if_fail (CC_IS_NUMBER_ROW (self)); + g_return_if_fail (G_IS_SETTINGS (settings)); + + /* Make sure the key has uint or int value type, otherwise it can't map to a CcNumberRow */ + key_variant = g_settings_get_value (settings, key); + g_return_if_fail (g_variant_is_of_type (key_variant, G_VARIANT_TYPE_UINT32) || + g_variant_is_of_type (key_variant, G_VARIANT_TYPE_INT32)); + + g_settings_bind_with_mapping (settings, key, self, "selected", G_SETTINGS_BIND_DEFAULT, + number_row_settings_get_mapping, number_row_settings_set_mapping, + self, NULL); +} diff --git a/panels/common/cc-number-row.h b/panels/common/cc-number-row.h new file mode 100644 index 0000000000000000000000000000000000000000..f4726f647dd27bc17ed49016b4ba19001bfb2917 --- /dev/null +++ b/panels/common/cc-number-row.h @@ -0,0 +1,100 @@ +/* cc-number-row.h + * + * Copyright 2024 Matthijs Velsink + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +#pragma once + +#include + +G_BEGIN_DECLS + +/** + * CcNumberOrder: + * @CC_NUMBER_ORDER_FIRST: place number first in the list of the row + * @CC_NUMBER_ORDER_DEFAULT: use the `sort-type` of the row + * @CC_NUMBER_ORDER_LAST: place number last in the list of the row + * + * Defines a special, fixed ordering of a `CcNumberObject` inside a + * `CcNumberRow`. + */ +typedef enum +{ + CC_NUMBER_ORDER_FIRST, + CC_NUMBER_ORDER_DEFAULT, + CC_NUMBER_ORDER_LAST +} CcNumberOrder; + +/** + * CcNumberValueType: + * @CC_NUMBER_VALUE_CUSTOM: no expression is set on the row, use a custom one + * @CC_NUMBER_VALUE_STRING: always use the `string` property of the number + * @CC_NUMBER_VALUE_SECONDS: interpret the value as a number of seconds + * @CC_NUMBER_VALUE_MINUTES: interpret the value as a number of minutes + * @CC_NUMBER_VALUE_HOURS: interpret the value as a number of hours + * + * Defines how a `CcNumberRow` interprets a value in order to map it to + * a string in the list. + */ +typedef enum +{ + CC_NUMBER_VALUE_CUSTOM, + CC_NUMBER_VALUE_STRING, + CC_NUMBER_VALUE_SECONDS, + CC_NUMBER_VALUE_MINUTES, + CC_NUMBER_VALUE_HOURS +} CcNumberValueType; + +/** + * CcNumberSortType: + * @CC_NUMBER_SORT_ASCENDING: sort the list in ascending order + * @CC_NUMBER_SORT_DESCENDING: sort the list in descending order + * @CC_NUMBER_SORT_NONE: do not sort the list + * + * Defines how the list of a `CcNumberRow` is sorted. + */ +typedef enum +{ + CC_NUMBER_SORT_ASCENDING, + CC_NUMBER_SORT_DESCENDING, + CC_NUMBER_SORT_NONE +} CcNumberSortType; + +#define CC_TYPE_NUMBER_OBJECT (cc_number_object_get_type()) +G_DECLARE_FINAL_TYPE (CcNumberObject, cc_number_object, CC, NUMBER_OBJECT, GObject) + +CcNumberObject *cc_number_object_new (int value); +CcNumberObject *cc_number_object_new_full (int value, const char *string, CcNumberOrder order); + +int cc_number_object_get_value (CcNumberObject *self); +char* cc_number_object_get_string (CcNumberObject *self); +CcNumberOrder cc_number_object_get_order (CcNumberObject *self); + +#define CC_TYPE_NUMBER_ROW (cc_number_row_get_type()) +G_DECLARE_FINAL_TYPE (CcNumberRow, cc_number_row, CC, NUMBER_ROW, AdwComboRow) + +CcNumberRow *cc_number_row_new (CcNumberValueType value_type, CcNumberSortType sort_type); + +guint cc_number_row_add_value (CcNumberRow *self, int value); +guint cc_number_row_add_value_full (CcNumberRow *self, int value, const char *string, CcNumberOrder order); +int cc_number_row_get_value (CcNumberRow *self, guint position); +gboolean cc_number_row_has_value (CcNumberRow *self, int value, guint *position); + +void cc_number_row_bind_settings (CcNumberRow *self, GSettings *settings, const gchar *key); + +G_END_DECLS diff --git a/panels/common/meson.build b/panels/common/meson.build index 270bad8cbd8b71948da59b708bc5250fee783b89..825ba46cadc7be78495d09206f0147703968c56c 100644 --- a/panels/common/meson.build +++ b/panels/common/meson.build @@ -24,7 +24,7 @@ common_sources += gnome.mkenums( vtail: ' { 0, NULL, NULL }\n };\n etype = g_@type@_register_static ("@EnumName@", values);\n }\n return etype;\n}\n' ) -common_sources += gnome.mkenums_simple('cc-number-list-enums', sources: files('cc-number-list.h')) +common_sources += gnome.mkenums_simple('cc-number-row-enums', sources: files('cc-number-row.h')) common_sources += gnome.compile_resources( 'cc-common-resources', @@ -39,7 +39,7 @@ generates_sources_dep = declare_dependency( sources = files( 'cc-hostname-entry.c', - 'cc-number-list.c', + 'cc-number-row.c', 'cc-time-entry.c', 'cc-util.c', 'hostname-helper.c' diff --git a/panels/privacy/screen/cc-screen-page.c b/panels/privacy/screen/cc-screen-page.c index cba5b4513528a919fe9f21747ad2581b7841d232..ddb0a8830ea0ca7c8f211600d35762220dc037c8 100644 --- a/panels/privacy/screen/cc-screen-page.c +++ b/panels/privacy/screen/cc-screen-page.c @@ -21,7 +21,7 @@ */ #include "cc-screen-page.h" -#include "cc-number-list.h" +#include "cc-number-row.h" #include "panels/display/cc-display-config-manager-dbus.h" @@ -40,10 +40,8 @@ struct _CcScreenPage GCancellable *cancellable; - AdwComboRow *blank_screen_row; - CcNumberList *blank_screen_list; - AdwComboRow *lock_after_row; - CcNumberList *lock_after_list; + CcNumberRow *blank_screen_row; + CcNumberRow *lock_after_row; AdwPreferencesGroup *screen_privacy_group; GDBusProxy *usb_proxy; AdwSwitchRow *automatic_screen_lock_row; @@ -54,52 +52,6 @@ struct _CcScreenPage G_DEFINE_TYPE (CcScreenPage, cc_screen_page, ADW_TYPE_NAVIGATION_PAGE) -static void -on_lock_combo_changed_cb (AdwComboRow *combo_row, - GParamSpec *pspec, - CcScreenPage *self) -{ - int delay = cc_number_list_get_value (self->lock_after_list, - adw_combo_row_get_selected (combo_row)); - - g_settings_set_uint (self->lock_settings, "lock-delay", delay); -} - -static void -set_lock_delay_value (CcScreenPage *self, - gint value) -{ - guint position; - - if (!cc_number_list_has_value (self->lock_after_list, value, &position)) - position = cc_number_list_add_value (self->lock_after_list, value); - - adw_combo_row_set_selected (self->lock_after_row, position); -} - -static void -set_blank_screen_delay_value (CcScreenPage *self, - gint value) -{ - guint position; - - if (!cc_number_list_has_value (self->blank_screen_list, value, &position)) - position = cc_number_list_add_value (self->blank_screen_list, value); - - adw_combo_row_set_selected (self->blank_screen_row, position); -} - -static void -on_blank_screen_delay_changed_cb (AdwComboRow *combo_row, - GParamSpec *pspec, - CcScreenPage *self) -{ - int delay = cc_number_list_get_value (self->blank_screen_list, - adw_combo_row_get_selected (combo_row)); - - g_settings_set_uint (self->session_settings, "idle-delay", delay); -} - static void on_usb_protection_properties_changed_cb (GDBusProxy *usb_proxy, GVariant *changed_properties, @@ -177,23 +129,17 @@ cc_screen_page_class_init (CcScreenPageClass *klass) oclass->finalize = cc_screen_page_finalize; - g_type_ensure (CC_TYPE_NUMBER_LIST); + g_type_ensure (CC_TYPE_NUMBER_ROW); gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/privacy/screen/cc-screen-page.ui"); gtk_widget_class_bind_template_child (widget_class, CcScreenPage, automatic_screen_lock_row); gtk_widget_class_bind_template_child (widget_class, CcScreenPage, blank_screen_row); - gtk_widget_class_bind_template_child (widget_class, CcScreenPage, blank_screen_list); gtk_widget_class_bind_template_child (widget_class, CcScreenPage, lock_after_row); - gtk_widget_class_bind_template_child (widget_class, CcScreenPage, lock_after_list); gtk_widget_class_bind_template_child (widget_class, CcScreenPage, privacy_screen_row); gtk_widget_class_bind_template_child (widget_class, CcScreenPage, screen_privacy_group); gtk_widget_class_bind_template_child (widget_class, CcScreenPage, show_notifications_row); gtk_widget_class_bind_template_child (widget_class, CcScreenPage, usb_protection_row); - - gtk_widget_class_bind_template_callback (widget_class, on_blank_screen_delay_changed_cb); - gtk_widget_class_bind_template_callback (widget_class, on_lock_combo_changed_cb); - gtk_widget_class_bind_template_callback (widget_class, cc_number_object_to_string_for_seconds); } static void @@ -231,8 +177,6 @@ update_display_config (CcScreenPage *self) static void cc_screen_page_init (CcScreenPage *self) { - guint value; - gtk_widget_init_template (GTK_WIDGET (self)); self->cancellable = g_cancellable_new (); @@ -254,8 +198,9 @@ cc_screen_page_init (CcScreenPage *self) "sensitive", G_SETTINGS_BIND_GET); - value = g_settings_get_uint (self->lock_settings, "lock-delay"); - set_lock_delay_value (self, value); + cc_number_row_bind_settings (self->lock_after_row, + self->lock_settings, + "lock-delay"); g_settings_bind (self->notification_settings, "show-in-lock-screen", @@ -263,8 +208,9 @@ cc_screen_page_init (CcScreenPage *self) "active", G_SETTINGS_BIND_DEFAULT); - value = g_settings_get_uint (self->session_settings, "idle-delay"); - set_blank_screen_delay_value (self, value); + cc_number_row_bind_settings (self->blank_screen_row, + self->session_settings, + "idle-delay"); g_settings_bind (self->privacy_settings, "usb-protection", diff --git a/panels/privacy/screen/cc-screen-page.ui b/panels/privacy/screen/cc-screen-page.ui index a512f54f52b701e1999e71dd4fcd34f89f13f5f8..25c9be7212cecc93fad4812f5979f9e994858de1 100644 --- a/panels/privacy/screen/cc-screen-page.ui +++ b/panels/privacy/screen/cc-screen-page.ui @@ -16,16 +16,20 @@ - + _Blank Screen Delay Period of inactivity until screen blanks 2 true - - blank_screen_list - - + [60, 120, 180, 240, 300, 480, 600, 720, 900] + + + 0 + Never + last + + seconds @@ -40,16 +44,19 @@ - + Automatic _Screen Lock Delay Time from screen blank to screen lock 2 true - - lock_after_list - - + [30, 60, 120, 180, 300, 1800, 3600] + + + 0 + Screen Turns Off + + seconds @@ -94,26 +101,4 @@ - - - [60, 120, 180, 240, 300, 480, 600, 720, 900] - - - 0 - Never - last - - - - - - [30, 60, 120, 180, 300, 1800, 3600] - - - 0 - Screen Turns Off - - - -