From eda460ac1520add0cfd07d19a9f325b2dee75ed0 Mon Sep 17 00:00:00 2001 From: Mohammed Sadiq Date: Mon, 15 Feb 2021 11:04:34 +0530 Subject: [PATCH] provider: Use GListModel to track origins And adapt to changes It's easier to track changes if we are using GListModel than a GList. Also, eventually we shall have multiple providers, and we can use GtkFlattenListModel to merge multiple origins without manually managing pointers ourself. Since several widgets has APIs to handle GListModels, it will also help us create widgets from GListModels easily. --- plugins/dummy/calls-dummy-provider.c | 32 ++---- plugins/mm/calls-mm-origin.c | 15 +++ plugins/mm/calls-mm-origin.h | 2 + plugins/mm/calls-mm-provider.c | 105 +++++++++-------- plugins/ofono/calls-ofono-origin.c | 12 ++ plugins/ofono/calls-ofono-origin.h | 2 + plugins/ofono/calls-ofono-provider.c | 110 ++++++++---------- src/calls-manager.c | 106 ++++++++++-------- src/calls-manager.h | 2 +- src/calls-new-call-box.c | 162 ++++++++------------------- src/calls-provider.c | 26 +---- src/calls-provider.h | 4 +- src/ui/new-call-box.ui | 21 ++-- tests/setup-origin.c | 5 +- tests/test-manager.c | 31 ++--- tests/test-provider.c | 5 +- 16 files changed, 274 insertions(+), 366 deletions(-) diff --git a/plugins/dummy/calls-dummy-provider.c b/plugins/dummy/calls-dummy-provider.c index eac9ece..debbde8 100644 --- a/plugins/dummy/calls-dummy-provider.c +++ b/plugins/dummy/calls-dummy-provider.c @@ -35,7 +35,7 @@ struct _CallsDummyProvider { CallsProvider parent_instance; - GList *origins; + GListStore *origins; }; static void calls_dummy_provider_message_source_interface_init (CallsMessageSourceInterface *iface); @@ -61,13 +61,15 @@ G_DEFINE_DYNAMIC_TYPE_EXTENDED static gboolean usr1_handler (CallsDummyProvider *self) { - CallsDummyOrigin *origin; + GListModel *model; + g_autoptr(CallsDummyOrigin) origin = NULL; - g_return_val_if_fail (self->origins != NULL, FALSE); + model = G_LIST_MODEL (self->origins); + g_return_val_if_fail (g_list_model_get_n_items (model) > 0, FALSE); g_debug ("Received SIGUSR1, adding new incoming call"); - origin = CALLS_DUMMY_ORIGIN (self->origins->data); + origin = g_list_model_get_item (model, 0); calls_dummy_origin_create_inbound (origin, "0987654321"); return TRUE; @@ -85,12 +87,12 @@ calls_dummy_provider_get_status (CallsProvider *provider) return "Normal"; } -static GList * +static GListModel * calls_dummy_provider_get_origins (CallsProvider *provider) { CallsDummyProvider *self = CALLS_DUMMY_PROVIDER (provider); - return g_list_copy (self->origins); + return G_LIST_MODEL (self->origins); } static void @@ -111,19 +113,10 @@ constructed (GObject *object) static void dispose (GObject *object) { - gpointer origin; - GList *next; CallsDummyProvider *self = CALLS_DUMMY_PROVIDER (object); - while (self->origins != NULL) { - origin = self->origins->data; - next = self->origins->next; - g_list_free_1 (self->origins); - self->origins = next; - - g_signal_emit_by_name (self, "origin-removed", origin); - g_object_unref (origin); - } + g_list_store_remove_all (self->origins); + g_clear_object (&self->origins); G_OBJECT_CLASS (calls_dummy_provider_parent_class)->dispose (object); } @@ -153,6 +146,7 @@ calls_dummy_provider_message_source_interface_init (CallsMessageSourceInterface static void calls_dummy_provider_init (CallsDummyProvider *self) { + self->origins = g_list_store_new (CALLS_TYPE_DUMMY_ORIGIN); } @@ -161,9 +155,7 @@ calls_dummy_provider_add_origin (CallsDummyProvider *self, const gchar *name) { CallsDummyOrigin *origin = calls_dummy_origin_new (name); - self->origins = g_list_append (self->origins, origin); - - g_signal_emit_by_name (CALLS_PROVIDER (self), "origin-added", CALLS_ORIGIN (origin)); + g_list_store_append (self->origins, origin); } diff --git a/plugins/mm/calls-mm-origin.c b/plugins/mm/calls-mm-origin.c index f911cf9..d31ec29 100644 --- a/plugins/mm/calls-mm-origin.c +++ b/plugins/mm/calls-mm-origin.c @@ -869,3 +869,18 @@ calls_mm_origin_new (MMObject *mm_obj) "mm-object", mm_obj, NULL); } + +gboolean +calls_mm_origin_matches (CallsMMOrigin *self, + MMObject *mm_obj) +{ + g_return_val_if_fail (CALLS_IS_MM_ORIGIN (self), FALSE); + g_return_val_if_fail (MM_IS_OBJECT (mm_obj), FALSE); + + if (self->mm_obj) + return g_strcmp0 (mm_object_get_path (mm_obj), + mm_object_get_path (self->mm_obj)) == 0; + + return FALSE; +} + diff --git a/plugins/mm/calls-mm-origin.h b/plugins/mm/calls-mm-origin.h index daee945..527ff88 100644 --- a/plugins/mm/calls-mm-origin.h +++ b/plugins/mm/calls-mm-origin.h @@ -35,6 +35,8 @@ G_BEGIN_DECLS G_DECLARE_FINAL_TYPE (CallsMMOrigin, calls_mm_origin, CALLS, MM_ORIGIN, GObject); CallsMMOrigin *calls_mm_origin_new (MMObject *modem); +gboolean calls_mm_origin_matches (CallsMMOrigin *self, + MMObject *modem); G_END_DECLS diff --git a/plugins/mm/calls-mm-provider.c b/plugins/mm/calls-mm-provider.c index c257c8a..dc6a375 100644 --- a/plugins/mm/calls-mm-provider.c +++ b/plugins/mm/calls-mm-provider.c @@ -42,8 +42,8 @@ struct _CallsMMProvider guint watch_id; /** ModemManager object proxy */ MMManager *mm; - /** Map of D-Bus object paths to origins */ - GHashTable *origins; + /* A list of CallsOrigins */ + GListStore *origins; }; static void calls_mm_provider_message_source_interface_init (CallsMessageSourceInterface *iface); @@ -78,7 +78,7 @@ update_status (CallsMMProvider *self) { s = _("ModemManager unavailable"); } - else if (g_hash_table_size (self->origins) == 0) + else if (g_list_model_get_n_items (G_LIST_MODEL (self->origins)) == 0) { s = _("No voice-capable modem available"); } @@ -91,6 +91,32 @@ update_status (CallsMMProvider *self) } +gboolean +mm_provider_contains (CallsMMProvider *self, + MMObject *mm_obj) +{ + GListModel *model; + guint n_items; + + g_assert (CALLS_IS_MM_PROVIDER (self)); + g_assert (MM_OBJECT (mm_obj)); + + model = G_LIST_MODEL (self->origins); + n_items = g_list_model_get_n_items (model); + + for (guint i = 0; i < n_items; i++) + { + g_autoptr(CallsMMOrigin) origin = NULL; + + origin = g_list_model_get_item (model, i); + + if (calls_mm_origin_matches (origin, mm_obj)) + return TRUE; + } + + return FALSE; +} + static void add_origin (CallsMMProvider *self, GDBusObject *object) @@ -99,8 +125,9 @@ add_origin (CallsMMProvider *self, CallsMMOrigin *origin; const gchar *path; + mm_obj = MM_OBJECT (object); path = g_dbus_object_get_object_path (object); - if (g_hash_table_contains (self->origins, path)) + if (mm_provider_contains (self, mm_obj)) { g_warning ("New voice interface on existing" " origin with path `%s'", path); @@ -111,16 +138,10 @@ add_origin (CallsMMProvider *self, path); g_assert (MM_IS_OBJECT (object)); - mm_obj = MM_OBJECT (object); origin = calls_mm_origin_new (mm_obj); + g_list_store_append (self->origins, origin); - g_hash_table_insert (self->origins, - mm_object_dup_path (mm_obj), - origin); - - g_signal_emit_by_name (CALLS_PROVIDER (self), - "origin-added", origin); update_status (self); } @@ -151,24 +172,25 @@ remove_modem_object (CallsMMProvider *self, const gchar *path, GDBusObject *object) { - gpointer *origin; + GListModel *model; + guint n_items; - origin = g_hash_table_lookup (self->origins, path); - if (!origin) - { - return; - } + model = G_LIST_MODEL (self->origins); + n_items = g_list_model_get_n_items (model); - g_assert (CALLS_IS_ORIGIN (origin)); + for (guint i = 0; i < n_items; i++) { + g_autoptr (CallsMMOrigin) origin = NULL; - g_object_ref (origin); - g_hash_table_remove (self->origins, path); + origin = g_list_model_get_item (model, i); - g_signal_emit_by_name (CALLS_PROVIDER (self), - "origin-removed", CALLS_ORIGIN (origin)); - g_object_unref (origin); + if (calls_mm_origin_matches (origin, MM_OBJECT (object))) + { + g_list_store_remove (self->origins, i); + update_status (self); - update_status (self); + break; + } + } } @@ -299,35 +321,13 @@ mm_appeared_cb (GDBusConnection *connection, } -static void -clear_dbus (CallsMMProvider *self) -{ - GList *paths, *node; - gpointer origin; - - paths = g_hash_table_get_keys (self->origins); - - for (node = paths; node != NULL; node = node->next) - { - g_hash_table_steal_extended (self->origins, node->data, NULL, &origin); - g_signal_emit_by_name (CALLS_PROVIDER (self), - "origin-removed", CALLS_ORIGIN (origin)); - g_object_unref (origin); - } - - g_list_free_full (paths, g_free); - - g_clear_object (&self->mm); -} - - void mm_vanished_cb (GDBusConnection *connection, const gchar *name, CallsMMProvider *self) { g_debug ("ModemManager vanished from D-Bus"); - clear_dbus (self); + g_list_store_remove_all (self->origins); update_status (self); } @@ -346,12 +346,12 @@ calls_mm_provider_get_status (CallsProvider *provider) return self->status; } -static GList * +static GListModel * calls_mm_provider_get_origins (CallsProvider *provider) { CallsMMProvider *self = CALLS_MM_PROVIDER (provider); - return g_hash_table_get_values (self->origins); + return G_LIST_MODEL (self->origins); } static void @@ -384,7 +384,7 @@ dispose (GObject *object) self->watch_id = 0; } - clear_dbus (self); + g_list_store_remove_all (self->origins); G_OBJECT_CLASS (calls_mm_provider_parent_class)->dispose (object); } @@ -395,7 +395,7 @@ finalize (GObject *object) { CallsMMProvider *self = CALLS_MM_PROVIDER (object); - g_hash_table_unref (self->origins); + g_object_unref (self->origins); g_free (self->status); G_OBJECT_CLASS (calls_mm_provider_parent_class)->finalize (object); @@ -433,8 +433,7 @@ static void calls_mm_provider_init (CallsMMProvider *self) { self->status = g_strdup (_("Initialised")); - self->origins = g_hash_table_new_full (g_str_hash, g_str_equal, - g_free, g_object_unref); + self->origins = g_list_store_new (CALLS_TYPE_MM_ORIGIN); } diff --git a/plugins/ofono/calls-ofono-origin.c b/plugins/ofono/calls-ofono-origin.c index 5eafc39..8e3fb00 100644 --- a/plugins/ofono/calls-ofono-origin.c +++ b/plugins/ofono/calls-ofono-origin.c @@ -110,6 +110,18 @@ calls_ofono_origin_new (GDBOModem *modem) NULL); } +gboolean +calls_ofono_origin_matches (CallsOfonoOrigin *self, + const char *path) +{ + g_return_val_if_fail (CALLS_IS_OFONO_ORIGIN (self), FALSE); + g_return_val_if_fail (path, FALSE); + + if (!self->modem) + return FALSE; + + return g_strcmp0 (g_dbus_proxy_get_object_path (G_DBUS_PROXY (self->modem)), path) == 0; +} static void set_property (GObject *object, diff --git a/plugins/ofono/calls-ofono-origin.h b/plugins/ofono/calls-ofono-origin.h index 2e3c30f..c21007d 100644 --- a/plugins/ofono/calls-ofono-origin.h +++ b/plugins/ofono/calls-ofono-origin.h @@ -36,6 +36,8 @@ G_BEGIN_DECLS G_DECLARE_FINAL_TYPE (CallsOfonoOrigin, calls_ofono_origin, CALLS, OFONO_ORIGIN, GObject); CallsOfonoOrigin *calls_ofono_origin_new (GDBOModem *modem); +gboolean calls_ofono_origin_matches (CallsOfonoOrigin *self, + const char *path); G_END_DECLS diff --git a/plugins/ofono/calls-ofono-provider.c b/plugins/ofono/calls-ofono-provider.c index 98aef1b..e78fd15 100644 --- a/plugins/ofono/calls-ofono-provider.c +++ b/plugins/ofono/calls-ofono-provider.c @@ -45,8 +45,8 @@ struct _CallsOfonoProvider GDBOManager *manager; /** Map of D-Bus object paths to a struct CallsModemData */ GHashTable *modems; - /** Map of D-Bus object paths to Origins */ - GHashTable *origins; + /* A list of CallsOrigins */ + GListStore *origins; }; @@ -59,47 +59,37 @@ G_DEFINE_DYNAMIC_TYPE_EXTENDED calls_ofono_provider_message_source_interface_init)) -static void -add_origin_to_list (const gchar *path, - CallsOfonoOrigin *origin, - GList **list) +gboolean +ofono_find_origin_index (CallsOfonoProvider *self, + const char *path, + guint *index) { - *list = g_list_prepend (*list, origin); + GListModel *model; + guint n_items; + + g_assert (CALLS_IS_OFONO_PROVIDER (self)); + + model = G_LIST_MODEL (self->origins); + n_items = g_list_model_get_n_items (model); + + for (guint i = 0; i < n_items; i++) + { + g_autoptr(CallsOfonoOrigin) origin = NULL; + + origin = g_list_model_get_item (model, i); + + if (calls_ofono_origin_matches (origin, path)) + { + if (index) + *index = i; + + return TRUE; + } + } + + return FALSE; } - -static void -add_origin (CallsOfonoProvider *self, - const gchar *path, - GDBOModem *modem) -{ - CallsOfonoOrigin *origin; - - g_debug ("Adding oFono Origin with path `%s'", path); - - origin = calls_ofono_origin_new (modem); - g_hash_table_insert (self->origins, g_strdup(path), origin); - - g_signal_emit_by_name (CALLS_PROVIDER (self), - "origin-added", origin); -} - - -static void -remove_origin (CallsOfonoProvider *self, - const gchar *path, - CallsOfonoOrigin *origin) -{ - g_debug ("Removing oFono Origin with path `%s'", path); - - g_signal_emit_by_name (CALLS_PROVIDER (self), - "origin-removed", origin); - - g_hash_table_remove (self->origins, path); - g_object_unref (origin); -} - - static gboolean object_array_includes (GVariantIter *iter, const gchar *needle) @@ -129,7 +119,8 @@ modem_check_ifaces (CallsOfonoProvider *self, gboolean voice; GVariantIter *iter = NULL; const gchar *path; - CallsOfonoOrigin *origin; + guint index; + gboolean has_origin; g_variant_get (ifaces, "as", &iter); @@ -137,15 +128,20 @@ modem_check_ifaces (CallsOfonoProvider *self, (iter, "org.ofono.VoiceCallManager"); path = g_dbus_proxy_get_object_path (G_DBUS_PROXY (modem)); - origin = g_hash_table_lookup (self->origins, path); - if (voice && !origin) + has_origin = ofono_find_origin_index (self, path, &index); + if (voice && !has_origin) { - add_origin (self, path, modem); + g_autoptr(CallsOfonoOrigin) origin = NULL; + + g_debug ("Adding oFono Origin with path `%s'", path); + + origin = calls_ofono_origin_new (modem); + g_list_store_append (self->origins, origin); } - else if (!voice && origin) + else if (!voice && has_origin) { - remove_origin (self, path, origin); + g_list_store_remove (self->origins, index); } } @@ -297,15 +293,12 @@ modem_removed_cb (GDBOManager *manager, const gchar *path, CallsOfonoProvider *self) { - CallsOfonoOrigin *origin; + guint index; g_debug ("Removing modem `%s'", path); - origin = g_hash_table_lookup (self->origins, path); - if (origin) - { - remove_origin (self, path, origin); - } + if (ofono_find_origin_index (self, path, &index)) + g_list_store_remove (self->origins, index); g_hash_table_remove (self->modems, path); @@ -365,16 +358,12 @@ calls_ofono_provider_get_status (CallsProvider *provider) return ""; } -static GList * +static GListModel * calls_ofono_provider_get_origins (CallsProvider *provider) { CallsOfonoProvider *self = CALLS_OFONO_PROVIDER (provider); - GList *list = NULL; - g_hash_table_foreach (self->origins, - (GHFunc)add_origin_to_list, &list); - - return g_list_reverse (list); + return G_LIST_MODEL (self->origins); } @@ -436,7 +425,7 @@ finalize (GObject *object) { CallsOfonoProvider *self = CALLS_OFONO_PROVIDER (object); - g_hash_table_unref (self->origins); + g_object_unref (self->origins); g_hash_table_unref (self->modems); G_OBJECT_CLASS (calls_ofono_provider_parent_class)->finalize (object); @@ -476,8 +465,7 @@ calls_ofono_provider_init (CallsOfonoProvider *self) { self->modems = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); - self->origins = g_hash_table_new_full (g_str_hash, g_str_equal, - g_free, NULL); + self->origins = g_list_store_new (CALLS_TYPE_OFONO_ORIGIN); } diff --git a/src/calls-manager.c b/src/calls-manager.c index 364908b..883bdd9 100644 --- a/src/calls-manager.c +++ b/src/calls-manager.c @@ -55,8 +55,6 @@ static GParamSpec *props[PROP_LAST_PROP]; enum { - SIGNAL_ORIGIN_ADD, - SIGNAL_ORIGIN_REMOVE, SIGNAL_CALL_ADD, SIGNAL_CALL_REMOVE, /* TODO: currently this event isn't emitted since the plugins don't give use @@ -205,7 +203,6 @@ add_origin (CallsManager *self, CallsOrigin *origin, CallsProvider *provider) calls_origin_foreach_call(origin, (CallsOriginForeachCallFunc)add_call, self); set_state (self, CALLS_MANAGER_STATE_READY); - g_signal_emit (self, signals[SIGNAL_ORIGIN_ADD], 0, origin); } static void @@ -217,7 +214,7 @@ remove_call_cb (gpointer self, CallsCall *call, CallsOrigin *origin) static void remove_origin (CallsManager *self, CallsOrigin *origin, CallsProvider *provider) { - g_autoptr (GList) origins = NULL; + GListModel *origins; g_return_if_fail (CALLS_IS_ORIGIN (origin)); @@ -229,10 +226,8 @@ remove_origin (CallsManager *self, CallsOrigin *origin, CallsProvider *provider) calls_manager_set_default_origin (self, NULL); origins = calls_manager_get_origins (self); - if (origins == NULL) - set_state (self, CALLS_MANAGER_STATE_NO_ORIGIN); - - g_signal_emit (self, signals[SIGNAL_ORIGIN_REMOVE], 0, origin); + if (!origins || g_list_model_get_n_items (origins) == 0) + set_state (self, CALLS_MANAGER_STATE_NO_ORIGIN); } static void @@ -240,29 +235,59 @@ remove_provider (CallsManager *self) { PeasEngine *engine = peas_engine_get_default (); PeasPluginInfo *plugin = peas_engine_get_plugin_info (engine, self->provider_name); - g_autoptr (GList) origins = NULL; - GList *o; + GListModel *origins; + guint n_items; g_debug ("Remove provider: %s", calls_provider_get_name (self->provider)); g_signal_handlers_disconnect_by_data (self->provider, self); origins = calls_provider_get_origins (self->provider); + g_signal_handlers_disconnect_by_data (origins, self); + n_items = g_list_model_get_n_items (origins); - for (o = origins; o != NULL; o = o->next) + for (guint i = 0; i < n_items; i++) { - remove_origin (self, o->data, self->provider); + g_autoptr(CallsOrigin) origin = NULL; + + origin = g_list_model_get_item (origins, i); + remove_origin (self, origin, self->provider); } g_clear_pointer (&self->provider_name, g_free); peas_engine_unload_plugin (engine, plugin); + g_clear_object (&self->provider); set_state (self, CALLS_MANAGER_STATE_NO_PROVIDER); } +static void +origin_items_changed_cb (CallsManager *self) +{ + GListModel *origins; + guint n_items; + + g_assert (CALLS_IS_MANAGER (self)); + + origins = calls_provider_get_origins (self->provider); + n_items = g_list_model_get_n_items (origins); + + if (n_items) + set_state (self, CALLS_MANAGER_STATE_READY); + else + set_state (self, CALLS_MANAGER_STATE_NO_ORIGIN); + + for (guint i = 0; i < n_items; i++) + { + g_autoptr(CallsOrigin) origin = NULL; + + origin = g_list_model_get_item (origins, i); + add_origin (self, origin, self->provider); + } +} + static void add_provider (CallsManager *self, const gchar *name) { - g_autoptr (GList) origins = NULL; - GList *o; + GListModel *origins; /* We could eventually enable more then one provider, but for now let's use only one */ @@ -279,17 +304,17 @@ add_provider (CallsManager *self, const gchar *name) return; } - set_state (self, CALLS_MANAGER_STATE_NO_ORIGIN); + if (g_strcmp0 (name, "dummy") == 0) + set_state (self, CALLS_MANAGER_STATE_READY); + else + set_state (self, CALLS_MANAGER_STATE_NO_ORIGIN); origins = calls_provider_get_origins (self->provider); - g_signal_connect_swapped (self->provider, "origin-added", G_CALLBACK (add_origin), self); - g_signal_connect_swapped (self->provider, "origin-removed", G_CALLBACK (remove_origin), self); - - for (o = origins; o != NULL; o = o->next) - { - add_origin (self, o->data, self->provider); - } + g_signal_connect_object (origins, "items-changed", + G_CALLBACK (origin_items_changed_cb), self, + G_CONNECT_SWAPPED); + origin_items_changed_cb (self); self->provider_name = g_strdup (name); } @@ -366,26 +391,6 @@ calls_manager_class_init (CallsManagerClass *klass) object_class->set_property = calls_manager_set_property; object_class->finalize = calls_manager_finalize; - signals[SIGNAL_ORIGIN_ADD] = - g_signal_new ("origin-add", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_FIRST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, - 1, - CALLS_TYPE_ORIGIN); - - signals[SIGNAL_ORIGIN_REMOVE] = - g_signal_new ("origin-remove", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_FIRST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, - 1, - CALLS_TYPE_ORIGIN); - signals[SIGNAL_CALL_ADD] = g_signal_new ("call-add", G_TYPE_FROM_CLASS (klass), @@ -548,7 +553,7 @@ calls_manager_get_state (CallsManager *self) return self->state; } -GList * +GListModel * calls_manager_get_origins (CallsManager *self) { g_return_val_if_fail (CALLS_IS_MANAGER (self), NULL); @@ -562,16 +567,23 @@ calls_manager_get_origins (CallsManager *self) GList * calls_manager_get_calls (CallsManager *self) { - g_autoptr (GList) origins = NULL; + GListModel *origins = NULL; g_autoptr (GList) calls = NULL; - GList *o; + guint n_items = 0; g_return_val_if_fail (CALLS_IS_MANAGER (self), NULL); origins = calls_manager_get_origins (self); + if (origins) + n_items = g_list_model_get_n_items (origins); - for (o = origins; o != NULL; o = o->next) - calls = g_list_concat (calls, calls_origin_get_calls (o->data)); + for (guint i = 0; i < n_items; i++) + { + g_autoptr(CallsOrigin) origin = NULL; + + origin = g_list_model_get_item (origins, i); + calls = g_list_concat (calls, calls_origin_get_calls (origin)); + } return g_steal_pointer (&calls); } diff --git a/src/calls-manager.h b/src/calls-manager.h index dd21eac..534d398 100644 --- a/src/calls-manager.h +++ b/src/calls-manager.h @@ -54,7 +54,7 @@ void calls_manager_set_provider (CallsManager *self, const gchar *name); CallsProvider *calls_manager_get_real_provider (CallsManager *self); CallsManagerState calls_manager_get_state (CallsManager *self); -GList *calls_manager_get_origins (CallsManager *self); +GListModel *calls_manager_get_origins (CallsManager *self); GList *calls_manager_get_calls (CallsManager *self); void calls_manager_dial (CallsManager *self, CallsOrigin *origin, diff --git a/src/calls-new-call-box.c b/src/calls-new-call-box.c index 0378835..2f14d4c 100644 --- a/src/calls-new-call-box.c +++ b/src/calls-new-call-box.c @@ -35,8 +35,8 @@ struct _CallsNewCallBox { GtkBox parent_instance; - GtkListStore *origin_store; - GtkComboBox *origin_box; + GtkListBox *origin_list_box; + HdyComboRow *origin_list; GtkButton *backspace; HdyKeypad *keypad; GtkButton *dial; @@ -48,30 +48,20 @@ struct _CallsNewCallBox G_DEFINE_TYPE (CallsNewCallBox, calls_new_call_box, GTK_TYPE_BOX); -enum { - ORIGIN_STORE_COLUMN_NAME, - ORIGIN_STORE_COLUMN_ORIGIN -}; - - static CallsOrigin * get_origin (CallsNewCallBox *self) { - GtkTreeIter iter; - gboolean ok; - CallsOrigin *origin; + g_autoptr(CallsOrigin) origin = NULL; + GListModel *model; + int index = -1; - ok = gtk_combo_box_get_active_iter (self->origin_box, &iter); - if (!ok) - { - return NULL; - } + model = hdy_combo_row_get_model (self->origin_list); - gtk_tree_model_get (GTK_TREE_MODEL (self->origin_store), - &iter, - ORIGIN_STORE_COLUMN_ORIGIN, &origin, - -1); - g_assert (CALLS_IS_ORIGIN (origin)); + if (model) + index = hdy_combo_row_get_selected_index (self->origin_list); + + if (model && index >= 0) + origin = g_list_model_get_item (model, index); return origin; } @@ -170,120 +160,70 @@ dial_queued (CallsNewCallBox *self) g_list_foreach (self->dial_queue, (GFunc)dial_queued_cb, origin); - g_object_unref (origin); clear_dial_queue (self); } -void -update_origin_box (CallsNewCallBox *self) +char * +get_origin_name (gpointer item, + gpointer user_data) { - GtkTreeModel *origin_store = GTK_TREE_MODEL (self->origin_store); - GtkTreeIter iter; + g_assert (CALLS_IS_ORIGIN (item)); - if (!gtk_tree_model_get_iter_first (origin_store, &iter)) - { - gtk_widget_hide (GTK_WIDGET (self->origin_box)); - gtk_widget_set_sensitive (GTK_WIDGET (self->dial), FALSE); - return; - } + return g_strdup (calls_origin_get_name (item)); +} - /* We know there is at least one origin. */ +static void +origin_count_changed_cb (CallsNewCallBox *self) +{ + GListModel *origins; + guint n_items = 0; - gtk_widget_set_sensitive (GTK_WIDGET (self->dial), TRUE); + g_assert (CALLS_IS_NEW_CALL_BOX (self)); - if (!gtk_tree_model_iter_next (origin_store, &iter)) - { - gtk_combo_box_set_active (self->origin_box, 0); - gtk_widget_hide (GTK_WIDGET (self->origin_box)); - } + origins = calls_manager_get_origins (calls_manager_get_default ()); + n_items = g_list_model_get_n_items (origins); + + gtk_widget_set_visible (GTK_WIDGET (self->origin_list_box), n_items > 1); + gtk_widget_set_sensitive (GTK_WIDGET (self->dial), n_items > 0); + + if (n_items) + hdy_combo_row_bind_name_model (self->origin_list, origins, + get_origin_name, self, NULL); else - { - /* We know there are multiple origins. */ + hdy_combo_row_bind_name_model (self->origin_list, + NULL, NULL, NULL, NULL); - if (gtk_combo_box_get_active (self->origin_box) < 0) - { - gtk_combo_box_set_active (self->origin_box, 0); - } - - /* We know there are multiple origins and one is selected. */ - - gtk_widget_show (GTK_WIDGET (self->origin_box)); - } + if (n_items) + hdy_combo_row_set_selected_index (self->origin_list, 0); dial_queued (self); } - static void -add_origin (CallsNewCallBox *self, CallsOrigin *origin) +provider_changed_cb (CallsNewCallBox *self) { - GtkTreeIter iter; + GListModel *origins; - gtk_list_store_append (self->origin_store, &iter); - gtk_list_store_set (self->origin_store, &iter, - ORIGIN_STORE_COLUMN_NAME, calls_origin_get_name (origin), - ORIGIN_STORE_COLUMN_ORIGIN, G_OBJECT (origin), - -1); + g_assert (CALLS_IS_NEW_CALL_BOX (self)); - update_origin_box (self); + origins = calls_manager_get_origins (calls_manager_get_default ()); + g_signal_connect_object (origins, "items-changed", + G_CALLBACK (origin_count_changed_cb), self, + G_CONNECT_SWAPPED); } - -static void -remove_origin (CallsNewCallBox *self, CallsOrigin *origin) -{ - GtkTreeIter iter; - gboolean ok; - - ok = calls_list_store_find (self->origin_store, origin, - ORIGIN_STORE_COLUMN_ORIGIN, &iter); - g_return_if_fail (ok); - - gtk_list_store_remove (self->origin_store, &iter); - - update_origin_box (self); -} - - -static void -remove_origins (CallsNewCallBox *self) -{ - GtkTreeModel *model = GTK_TREE_MODEL (self->origin_store); - GtkTreeIter iter; - - while (gtk_tree_model_get_iter_first (model, &iter)) - { - gtk_list_store_remove (self->origin_store, &iter); - } -} - - static void calls_new_call_box_init (CallsNewCallBox *self) { - g_autoptr (GList) origins = NULL; - GList *o; - gtk_widget_init_template (GTK_WIDGET (self)); g_signal_connect_swapped (calls_manager_get_default (), - "origin-add", - G_CALLBACK (add_origin), + "notify::provider", + G_CALLBACK (provider_changed_cb), self); - - g_signal_connect_swapped (calls_manager_get_default (), - "origin-remove", - G_CALLBACK (remove_origin), - self); - - origins = calls_manager_get_origins (calls_manager_get_default ()); - for (o = origins; o != NULL; o = o->next) { - add_origin (self, o->data); - } - - update_origin_box (self); + provider_changed_cb (self); } @@ -294,11 +234,6 @@ dispose (GObject *object) clear_dial_queue (self); - if (self->origin_store) - { - remove_origins (self); - } - if (self->long_press_back_gesture != NULL) g_object_unref (self->long_press_back_gesture); @@ -315,8 +250,8 @@ calls_new_call_box_class_init (CallsNewCallBoxClass *klass) object_class->dispose = dispose; gtk_widget_class_set_template_from_resource (widget_class, "/sm/puri/calls/ui/new-call-box.ui"); - gtk_widget_class_bind_template_child (widget_class, CallsNewCallBox, origin_store); - gtk_widget_class_bind_template_child (widget_class, CallsNewCallBox, origin_box); + gtk_widget_class_bind_template_child (widget_class, CallsNewCallBox, origin_list_box); + gtk_widget_class_bind_template_child (widget_class, CallsNewCallBox, origin_list); gtk_widget_class_bind_template_child (widget_class, CallsNewCallBox, backspace); gtk_widget_class_bind_template_child (widget_class, CallsNewCallBox, long_press_back_gesture); gtk_widget_class_bind_template_child (widget_class, CallsNewCallBox, keypad); @@ -354,7 +289,6 @@ calls_new_call_box_dial (CallsNewCallBox *self, } calls_origin_dial (origin, target); - g_object_unref (origin); } void diff --git a/src/calls-provider.c b/src/calls-provider.c index b71f7f6..2eb8c5d 100644 --- a/src/calls-provider.c +++ b/src/calls-provider.c @@ -58,13 +58,6 @@ enum { static GParamSpec *props[PROP_LAST_PROP]; -enum { - SIGNAL_ORIGIN_ADDED, - SIGNAL_ORIGIN_REMOVED, - SIGNAL_LAST_SIGNAL, -}; -static guint signals [SIGNAL_LAST_SIGNAL]; - static void calls_provider_get_property (GObject *object, guint prop_id, @@ -99,20 +92,6 @@ calls_provider_class_init (CallsProviderClass *klass) G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_properties (object_class, PROP_LAST_PROP, props); - - signals[SIGNAL_ORIGIN_ADDED] = - g_signal_new ("origin-added", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, NULL, NULL, NULL, - G_TYPE_NONE, 1, CALLS_TYPE_ORIGIN); - - signals[SIGNAL_ORIGIN_REMOVED] = - g_signal_new ("origin-removed", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, NULL, NULL, NULL, - G_TYPE_NONE, 1, CALLS_TYPE_ORIGIN); } static void @@ -151,10 +130,9 @@ calls_provider_get_status (CallsProvider *self) * * Get the list of #CallsOrigin interfaces offered by this provider. * - * Returns: A newly-allocated GList of objects implementing - * #CallsOrigin or NULL if there was an error. + * Returns: (transfer none): A #GListModel of origins */ -GList * +GListModel * calls_provider_get_origins (CallsProvider *self) { g_return_val_if_fail (CALLS_IS_PROVIDER (self), NULL); diff --git a/src/calls-provider.h b/src/calls-provider.h index fdd8afb..0288d94 100644 --- a/src/calls-provider.h +++ b/src/calls-provider.h @@ -46,13 +46,13 @@ struct _CallsProviderClass const char *(*get_name) (CallsProvider *self); const char *(*get_status) (CallsProvider *self); - GList *(*get_origins) (CallsProvider *self); + GListModel *(*get_origins) (CallsProvider *self); }; const char *calls_provider_get_name (CallsProvider *self); const char *calls_provider_get_status (CallsProvider *self); -GList *calls_provider_get_origins (CallsProvider *self); +GListModel *calls_provider_get_origins (CallsProvider *self); G_END_DECLS diff --git a/src/ui/new-call-box.ui b/src/ui/new-call-box.ui index 1cd8126..df23261 100644 --- a/src/ui/new-call-box.ui +++ b/src/ui/new-call-box.ui @@ -21,26 +21,19 @@ vertical center True + - - False - origin_store - 0 - 8 - True + True + none - - - 0 - + + True + - - False - True - + True diff --git a/tests/setup-origin.c b/tests/setup-origin.c index cd927dc..e7d0c11 100644 --- a/tests/setup-origin.c +++ b/tests/setup-origin.c @@ -11,7 +11,7 @@ void test_dummy_origin_set_up (OriginFixture *fixture, gconstpointer user_data) { - GList *origins; + GListModel *origins; test_dummy_provider_set_up (&fixture->parent, user_data); @@ -20,8 +20,7 @@ test_dummy_origin_set_up (OriginFixture *fixture, origins = calls_provider_get_origins (CALLS_PROVIDER (fixture->parent.dummy_provider)); - fixture->dummy_origin = CALLS_DUMMY_ORIGIN (origins->data); - g_list_free (origins); + fixture->dummy_origin = g_list_model_get_item (origins, 0); } diff --git a/tests/test-manager.c b/tests/test-manager.c index b0256c6..1a1de90 100644 --- a/tests/test-manager.c +++ b/tests/test-manager.c @@ -9,21 +9,8 @@ #include #include -gint origin_count = 0; CallsCall *test_call = NULL; -static void -origin_add_cb (CallsManager *manager) -{ - origin_count++; -} - -static void -origin_remove_cb (CallsManager *manager) -{ - origin_count--; -} - static void call_add_cb (CallsManager *manager, CallsCall *call) { @@ -54,36 +41,32 @@ static void test_calls_manager_dummy_provider () { g_autoptr (CallsManager) manager = calls_manager_new (); - g_autoptr (GList) origins = NULL; - gint no_origins = 0; + GListModel *origins; CallsOrigin *origin; g_assert (CALLS_IS_MANAGER (manager)); - origin_count = 0; - g_signal_connect (manager, "origin-remove", G_CALLBACK (origin_remove_cb), NULL); - g_signal_connect (manager, "origin-add", G_CALLBACK (origin_add_cb), NULL); - g_assert_null (calls_manager_get_provider (manager)); g_assert (calls_manager_get_state (manager) == CALLS_MANAGER_STATE_NO_PROVIDER); + g_assert_null (calls_manager_get_origins (manager)); calls_manager_set_provider (manager, "dummy"); g_assert_cmpstr (calls_manager_get_provider (manager), ==, "dummy"); g_assert (calls_manager_get_state (manager) == CALLS_MANAGER_STATE_READY); + g_assert_nonnull (calls_manager_get_origins (manager)); origins = calls_manager_get_origins (manager); - no_origins = g_list_length (origins); - g_assert_cmpint (origin_count, ==, no_origins); g_assert_nonnull (calls_manager_get_origins (manager)); + g_assert_true (g_list_model_get_n_items (origins) > 0); g_assert_null (calls_manager_get_calls (manager)); g_assert_null (calls_manager_get_default_origin (manager)); test_call = NULL; - if (no_origins > 0) { + if (g_list_model_get_n_items (origins) > 0) { g_signal_connect (manager, "call-add", G_CALLBACK (call_add_cb), NULL); g_signal_connect (manager, "call-remove", G_CALLBACK (call_remove_cb), NULL); - origin = CALLS_ORIGIN (g_list_first (origins)->data); + origin = g_list_model_get_item (origins, 0); g_assert (CALLS_IS_ORIGIN (origin)); calls_manager_set_default_origin (manager, origin); @@ -101,8 +84,8 @@ test_calls_manager_dummy_provider () /* Unload the provider */ calls_manager_set_provider (manager, NULL); - g_assert_cmpint (origin_count, ==, 0); g_assert_null (test_call); + g_assert_null (calls_manager_get_origins (manager)); g_assert (calls_manager_get_state (manager) == CALLS_MANAGER_STATE_NO_PROVIDER); } diff --git a/tests/test-provider.c b/tests/test-provider.c index 6c16ae7..16f3f56 100644 --- a/tests/test-provider.c +++ b/tests/test-provider.c @@ -41,12 +41,11 @@ static void test_dummy_provider_origins (ProviderFixture *fixture, gconstpointer user_data) { - GList *origins; + GListModel *origins; origins = calls_provider_get_origins (CALLS_PROVIDER (fixture->dummy_provider)); - g_assert_cmpuint (g_list_length (origins), ==, 1); - g_list_free (origins); + g_assert_cmpuint (g_list_model_get_n_items (origins), ==, 1); }