1
0
Fork 0
mirror of https://gitlab.gnome.org/GNOME/calls.git synced 2024-06-24 12:49:30 +00:00

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.
This commit is contained in:
Mohammed Sadiq 2021-02-15 11:04:34 +05:30
parent b5645c4cca
commit eda460ac15
16 changed files with 274 additions and 366 deletions

View file

@ -35,7 +35,7 @@ struct _CallsDummyProvider
{ {
CallsProvider parent_instance; CallsProvider parent_instance;
GList *origins; GListStore *origins;
}; };
static void calls_dummy_provider_message_source_interface_init (CallsMessageSourceInterface *iface); static void calls_dummy_provider_message_source_interface_init (CallsMessageSourceInterface *iface);
@ -61,13 +61,15 @@ G_DEFINE_DYNAMIC_TYPE_EXTENDED
static gboolean static gboolean
usr1_handler (CallsDummyProvider *self) 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"); 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"); calls_dummy_origin_create_inbound (origin, "0987654321");
return TRUE; return TRUE;
@ -85,12 +87,12 @@ calls_dummy_provider_get_status (CallsProvider *provider)
return "Normal"; return "Normal";
} }
static GList * static GListModel *
calls_dummy_provider_get_origins (CallsProvider *provider) calls_dummy_provider_get_origins (CallsProvider *provider)
{ {
CallsDummyProvider *self = CALLS_DUMMY_PROVIDER (provider); CallsDummyProvider *self = CALLS_DUMMY_PROVIDER (provider);
return g_list_copy (self->origins); return G_LIST_MODEL (self->origins);
} }
static void static void
@ -111,19 +113,10 @@ constructed (GObject *object)
static void static void
dispose (GObject *object) dispose (GObject *object)
{ {
gpointer origin;
GList *next;
CallsDummyProvider *self = CALLS_DUMMY_PROVIDER (object); CallsDummyProvider *self = CALLS_DUMMY_PROVIDER (object);
while (self->origins != NULL) { g_list_store_remove_all (self->origins);
origin = self->origins->data; g_clear_object (&self->origins);
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_OBJECT_CLASS (calls_dummy_provider_parent_class)->dispose (object); G_OBJECT_CLASS (calls_dummy_provider_parent_class)->dispose (object);
} }
@ -153,6 +146,7 @@ calls_dummy_provider_message_source_interface_init (CallsMessageSourceInterface
static void static void
calls_dummy_provider_init (CallsDummyProvider *self) 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) const gchar *name)
{ {
CallsDummyOrigin *origin = calls_dummy_origin_new (name); CallsDummyOrigin *origin = calls_dummy_origin_new (name);
self->origins = g_list_append (self->origins, origin); g_list_store_append (self->origins, origin);
g_signal_emit_by_name (CALLS_PROVIDER (self), "origin-added", CALLS_ORIGIN (origin));
} }

View file

@ -869,3 +869,18 @@ calls_mm_origin_new (MMObject *mm_obj)
"mm-object", mm_obj, "mm-object", mm_obj,
NULL); 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;
}

View file

@ -35,6 +35,8 @@ G_BEGIN_DECLS
G_DECLARE_FINAL_TYPE (CallsMMOrigin, calls_mm_origin, CALLS, MM_ORIGIN, GObject); G_DECLARE_FINAL_TYPE (CallsMMOrigin, calls_mm_origin, CALLS, MM_ORIGIN, GObject);
CallsMMOrigin *calls_mm_origin_new (MMObject *modem); CallsMMOrigin *calls_mm_origin_new (MMObject *modem);
gboolean calls_mm_origin_matches (CallsMMOrigin *self,
MMObject *modem);
G_END_DECLS G_END_DECLS

View file

@ -42,8 +42,8 @@ struct _CallsMMProvider
guint watch_id; guint watch_id;
/** ModemManager object proxy */ /** ModemManager object proxy */
MMManager *mm; MMManager *mm;
/** Map of D-Bus object paths to origins */ /* A list of CallsOrigins */
GHashTable *origins; GListStore *origins;
}; };
static void calls_mm_provider_message_source_interface_init (CallsMessageSourceInterface *iface); static void calls_mm_provider_message_source_interface_init (CallsMessageSourceInterface *iface);
@ -78,7 +78,7 @@ update_status (CallsMMProvider *self)
{ {
s = _("ModemManager unavailable"); 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"); 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 static void
add_origin (CallsMMProvider *self, add_origin (CallsMMProvider *self,
GDBusObject *object) GDBusObject *object)
@ -99,8 +125,9 @@ add_origin (CallsMMProvider *self,
CallsMMOrigin *origin; CallsMMOrigin *origin;
const gchar *path; const gchar *path;
mm_obj = MM_OBJECT (object);
path = g_dbus_object_get_object_path (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" g_warning ("New voice interface on existing"
" origin with path `%s'", path); " origin with path `%s'", path);
@ -111,16 +138,10 @@ add_origin (CallsMMProvider *self,
path); path);
g_assert (MM_IS_OBJECT (object)); g_assert (MM_IS_OBJECT (object));
mm_obj = MM_OBJECT (object);
origin = calls_mm_origin_new (mm_obj); 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); update_status (self);
} }
@ -151,24 +172,25 @@ remove_modem_object (CallsMMProvider *self,
const gchar *path, const gchar *path,
GDBusObject *object) GDBusObject *object)
{ {
gpointer *origin; GListModel *model;
guint n_items;
origin = g_hash_table_lookup (self->origins, path); model = G_LIST_MODEL (self->origins);
if (!origin) n_items = g_list_model_get_n_items (model);
{
return;
}
g_assert (CALLS_IS_ORIGIN (origin)); for (guint i = 0; i < n_items; i++) {
g_autoptr (CallsMMOrigin) origin = NULL;
g_object_ref (origin); origin = g_list_model_get_item (model, i);
g_hash_table_remove (self->origins, path);
g_signal_emit_by_name (CALLS_PROVIDER (self), if (calls_mm_origin_matches (origin, MM_OBJECT (object)))
"origin-removed", CALLS_ORIGIN (origin)); {
g_object_unref (origin); 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 void
mm_vanished_cb (GDBusConnection *connection, mm_vanished_cb (GDBusConnection *connection,
const gchar *name, const gchar *name,
CallsMMProvider *self) CallsMMProvider *self)
{ {
g_debug ("ModemManager vanished from D-Bus"); g_debug ("ModemManager vanished from D-Bus");
clear_dbus (self); g_list_store_remove_all (self->origins);
update_status (self); update_status (self);
} }
@ -346,12 +346,12 @@ calls_mm_provider_get_status (CallsProvider *provider)
return self->status; return self->status;
} }
static GList * static GListModel *
calls_mm_provider_get_origins (CallsProvider *provider) calls_mm_provider_get_origins (CallsProvider *provider)
{ {
CallsMMProvider *self = CALLS_MM_PROVIDER (provider); CallsMMProvider *self = CALLS_MM_PROVIDER (provider);
return g_hash_table_get_values (self->origins); return G_LIST_MODEL (self->origins);
} }
static void static void
@ -384,7 +384,7 @@ dispose (GObject *object)
self->watch_id = 0; self->watch_id = 0;
} }
clear_dbus (self); g_list_store_remove_all (self->origins);
G_OBJECT_CLASS (calls_mm_provider_parent_class)->dispose (object); G_OBJECT_CLASS (calls_mm_provider_parent_class)->dispose (object);
} }
@ -395,7 +395,7 @@ finalize (GObject *object)
{ {
CallsMMProvider *self = CALLS_MM_PROVIDER (object); CallsMMProvider *self = CALLS_MM_PROVIDER (object);
g_hash_table_unref (self->origins); g_object_unref (self->origins);
g_free (self->status); g_free (self->status);
G_OBJECT_CLASS (calls_mm_provider_parent_class)->finalize (object); G_OBJECT_CLASS (calls_mm_provider_parent_class)->finalize (object);
@ -433,8 +433,7 @@ static void
calls_mm_provider_init (CallsMMProvider *self) calls_mm_provider_init (CallsMMProvider *self)
{ {
self->status = g_strdup (_("Initialised")); self->status = g_strdup (_("Initialised"));
self->origins = g_hash_table_new_full (g_str_hash, g_str_equal, self->origins = g_list_store_new (CALLS_TYPE_MM_ORIGIN);
g_free, g_object_unref);
} }

View file

@ -110,6 +110,18 @@ calls_ofono_origin_new (GDBOModem *modem)
NULL); 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 static void
set_property (GObject *object, set_property (GObject *object,

View file

@ -36,6 +36,8 @@ G_BEGIN_DECLS
G_DECLARE_FINAL_TYPE (CallsOfonoOrigin, calls_ofono_origin, CALLS, OFONO_ORIGIN, GObject); G_DECLARE_FINAL_TYPE (CallsOfonoOrigin, calls_ofono_origin, CALLS, OFONO_ORIGIN, GObject);
CallsOfonoOrigin *calls_ofono_origin_new (GDBOModem *modem); CallsOfonoOrigin *calls_ofono_origin_new (GDBOModem *modem);
gboolean calls_ofono_origin_matches (CallsOfonoOrigin *self,
const char *path);
G_END_DECLS G_END_DECLS

View file

@ -45,8 +45,8 @@ struct _CallsOfonoProvider
GDBOManager *manager; GDBOManager *manager;
/** Map of D-Bus object paths to a struct CallsModemData */ /** Map of D-Bus object paths to a struct CallsModemData */
GHashTable *modems; GHashTable *modems;
/** Map of D-Bus object paths to Origins */ /* A list of CallsOrigins */
GHashTable *origins; GListStore *origins;
}; };
@ -59,47 +59,37 @@ G_DEFINE_DYNAMIC_TYPE_EXTENDED
calls_ofono_provider_message_source_interface_init)) calls_ofono_provider_message_source_interface_init))
static void gboolean
add_origin_to_list (const gchar *path, ofono_find_origin_index (CallsOfonoProvider *self,
CallsOfonoOrigin *origin, const char *path,
GList **list) 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 static gboolean
object_array_includes (GVariantIter *iter, object_array_includes (GVariantIter *iter,
const gchar *needle) const gchar *needle)
@ -129,7 +119,8 @@ modem_check_ifaces (CallsOfonoProvider *self,
gboolean voice; gboolean voice;
GVariantIter *iter = NULL; GVariantIter *iter = NULL;
const gchar *path; const gchar *path;
CallsOfonoOrigin *origin; guint index;
gboolean has_origin;
g_variant_get (ifaces, "as", &iter); g_variant_get (ifaces, "as", &iter);
@ -137,15 +128,20 @@ modem_check_ifaces (CallsOfonoProvider *self,
(iter, "org.ofono.VoiceCallManager"); (iter, "org.ofono.VoiceCallManager");
path = g_dbus_proxy_get_object_path (G_DBUS_PROXY (modem)); 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, const gchar *path,
CallsOfonoProvider *self) CallsOfonoProvider *self)
{ {
CallsOfonoOrigin *origin; guint index;
g_debug ("Removing modem `%s'", path); g_debug ("Removing modem `%s'", path);
origin = g_hash_table_lookup (self->origins, path); if (ofono_find_origin_index (self, path, &index))
if (origin) g_list_store_remove (self->origins, index);
{
remove_origin (self, path, origin);
}
g_hash_table_remove (self->modems, path); g_hash_table_remove (self->modems, path);
@ -365,16 +358,12 @@ calls_ofono_provider_get_status (CallsProvider *provider)
return ""; return "";
} }
static GList * static GListModel *
calls_ofono_provider_get_origins (CallsProvider *provider) calls_ofono_provider_get_origins (CallsProvider *provider)
{ {
CallsOfonoProvider *self = CALLS_OFONO_PROVIDER (provider); CallsOfonoProvider *self = CALLS_OFONO_PROVIDER (provider);
GList *list = NULL;
g_hash_table_foreach (self->origins, return G_LIST_MODEL (self->origins);
(GHFunc)add_origin_to_list, &list);
return g_list_reverse (list);
} }
@ -436,7 +425,7 @@ finalize (GObject *object)
{ {
CallsOfonoProvider *self = CALLS_OFONO_PROVIDER (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_hash_table_unref (self->modems);
G_OBJECT_CLASS (calls_ofono_provider_parent_class)->finalize (object); 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, self->modems = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, g_object_unref); g_free, g_object_unref);
self->origins = g_hash_table_new_full (g_str_hash, g_str_equal, self->origins = g_list_store_new (CALLS_TYPE_OFONO_ORIGIN);
g_free, NULL);
} }

View file

@ -55,8 +55,6 @@ static GParamSpec *props[PROP_LAST_PROP];
enum { enum {
SIGNAL_ORIGIN_ADD,
SIGNAL_ORIGIN_REMOVE,
SIGNAL_CALL_ADD, SIGNAL_CALL_ADD,
SIGNAL_CALL_REMOVE, SIGNAL_CALL_REMOVE,
/* TODO: currently this event isn't emitted since the plugins don't give use /* 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); calls_origin_foreach_call(origin, (CallsOriginForeachCallFunc)add_call, self);
set_state (self, CALLS_MANAGER_STATE_READY); set_state (self, CALLS_MANAGER_STATE_READY);
g_signal_emit (self, signals[SIGNAL_ORIGIN_ADD], 0, origin);
} }
static void static void
@ -217,7 +214,7 @@ remove_call_cb (gpointer self, CallsCall *call, CallsOrigin *origin)
static void static void
remove_origin (CallsManager *self, CallsOrigin *origin, CallsProvider *provider) remove_origin (CallsManager *self, CallsOrigin *origin, CallsProvider *provider)
{ {
g_autoptr (GList) origins = NULL; GListModel *origins;
g_return_if_fail (CALLS_IS_ORIGIN (origin)); 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); calls_manager_set_default_origin (self, NULL);
origins = calls_manager_get_origins (self); origins = calls_manager_get_origins (self);
if (origins == NULL) if (!origins || g_list_model_get_n_items (origins) == 0)
set_state (self, CALLS_MANAGER_STATE_NO_ORIGIN); set_state (self, CALLS_MANAGER_STATE_NO_ORIGIN);
g_signal_emit (self, signals[SIGNAL_ORIGIN_REMOVE], 0, origin);
} }
static void static void
@ -240,29 +235,59 @@ remove_provider (CallsManager *self)
{ {
PeasEngine *engine = peas_engine_get_default (); PeasEngine *engine = peas_engine_get_default ();
PeasPluginInfo *plugin = peas_engine_get_plugin_info (engine, self->provider_name); PeasPluginInfo *plugin = peas_engine_get_plugin_info (engine, self->provider_name);
g_autoptr (GList) origins = NULL; GListModel *origins;
GList *o; guint n_items;
g_debug ("Remove provider: %s", calls_provider_get_name (self->provider)); g_debug ("Remove provider: %s", calls_provider_get_name (self->provider));
g_signal_handlers_disconnect_by_data (self->provider, self); g_signal_handlers_disconnect_by_data (self->provider, self);
origins = calls_provider_get_origins (self->provider); 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); g_clear_pointer (&self->provider_name, g_free);
peas_engine_unload_plugin (engine, plugin); peas_engine_unload_plugin (engine, plugin);
g_clear_object (&self->provider);
set_state (self, CALLS_MANAGER_STATE_NO_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 static void
add_provider (CallsManager *self, const gchar *name) add_provider (CallsManager *self, const gchar *name)
{ {
g_autoptr (GList) origins = NULL; GListModel *origins;
GList *o;
/* We could eventually enable more then one provider, but for now let's use /* We could eventually enable more then one provider, but for now let's use
only one */ only one */
@ -279,17 +304,17 @@ add_provider (CallsManager *self, const gchar *name)
return; 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); origins = calls_provider_get_origins (self->provider);
g_signal_connect_swapped (self->provider, "origin-added", G_CALLBACK (add_origin), self); g_signal_connect_object (origins, "items-changed",
g_signal_connect_swapped (self->provider, "origin-removed", G_CALLBACK (remove_origin), self); G_CALLBACK (origin_items_changed_cb), self,
G_CONNECT_SWAPPED);
for (o = origins; o != NULL; o = o->next) origin_items_changed_cb (self);
{
add_origin (self, o->data, self->provider);
}
self->provider_name = g_strdup (name); 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->set_property = calls_manager_set_property;
object_class->finalize = calls_manager_finalize; 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] = signals[SIGNAL_CALL_ADD] =
g_signal_new ("call-add", g_signal_new ("call-add",
G_TYPE_FROM_CLASS (klass), G_TYPE_FROM_CLASS (klass),
@ -548,7 +553,7 @@ calls_manager_get_state (CallsManager *self)
return self->state; return self->state;
} }
GList * GListModel *
calls_manager_get_origins (CallsManager *self) calls_manager_get_origins (CallsManager *self)
{ {
g_return_val_if_fail (CALLS_IS_MANAGER (self), NULL); g_return_val_if_fail (CALLS_IS_MANAGER (self), NULL);
@ -562,16 +567,23 @@ calls_manager_get_origins (CallsManager *self)
GList * GList *
calls_manager_get_calls (CallsManager *self) calls_manager_get_calls (CallsManager *self)
{ {
g_autoptr (GList) origins = NULL; GListModel *origins = NULL;
g_autoptr (GList) calls = NULL; g_autoptr (GList) calls = NULL;
GList *o; guint n_items = 0;
g_return_val_if_fail (CALLS_IS_MANAGER (self), NULL); g_return_val_if_fail (CALLS_IS_MANAGER (self), NULL);
origins = calls_manager_get_origins (self); 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) for (guint i = 0; i < n_items; i++)
calls = g_list_concat (calls, calls_origin_get_calls (o->data)); {
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); return g_steal_pointer (&calls);
} }

View file

@ -54,7 +54,7 @@ void calls_manager_set_provider (CallsManager *self,
const gchar *name); const gchar *name);
CallsProvider *calls_manager_get_real_provider (CallsManager *self); CallsProvider *calls_manager_get_real_provider (CallsManager *self);
CallsManagerState calls_manager_get_state (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); GList *calls_manager_get_calls (CallsManager *self);
void calls_manager_dial (CallsManager *self, void calls_manager_dial (CallsManager *self,
CallsOrigin *origin, CallsOrigin *origin,

View file

@ -35,8 +35,8 @@ struct _CallsNewCallBox
{ {
GtkBox parent_instance; GtkBox parent_instance;
GtkListStore *origin_store; GtkListBox *origin_list_box;
GtkComboBox *origin_box; HdyComboRow *origin_list;
GtkButton *backspace; GtkButton *backspace;
HdyKeypad *keypad; HdyKeypad *keypad;
GtkButton *dial; GtkButton *dial;
@ -48,30 +48,20 @@ struct _CallsNewCallBox
G_DEFINE_TYPE (CallsNewCallBox, calls_new_call_box, GTK_TYPE_BOX); G_DEFINE_TYPE (CallsNewCallBox, calls_new_call_box, GTK_TYPE_BOX);
enum {
ORIGIN_STORE_COLUMN_NAME,
ORIGIN_STORE_COLUMN_ORIGIN
};
static CallsOrigin * static CallsOrigin *
get_origin (CallsNewCallBox *self) get_origin (CallsNewCallBox *self)
{ {
GtkTreeIter iter; g_autoptr(CallsOrigin) origin = NULL;
gboolean ok; GListModel *model;
CallsOrigin *origin; int index = -1;
ok = gtk_combo_box_get_active_iter (self->origin_box, &iter); model = hdy_combo_row_get_model (self->origin_list);
if (!ok)
{
return NULL;
}
gtk_tree_model_get (GTK_TREE_MODEL (self->origin_store), if (model)
&iter, index = hdy_combo_row_get_selected_index (self->origin_list);
ORIGIN_STORE_COLUMN_ORIGIN, &origin,
-1); if (model && index >= 0)
g_assert (CALLS_IS_ORIGIN (origin)); origin = g_list_model_get_item (model, index);
return origin; return origin;
} }
@ -170,120 +160,70 @@ dial_queued (CallsNewCallBox *self)
g_list_foreach (self->dial_queue, g_list_foreach (self->dial_queue,
(GFunc)dial_queued_cb, (GFunc)dial_queued_cb,
origin); origin);
g_object_unref (origin);
clear_dial_queue (self); clear_dial_queue (self);
} }
void char *
update_origin_box (CallsNewCallBox *self) get_origin_name (gpointer item,
gpointer user_data)
{ {
GtkTreeModel *origin_store = GTK_TREE_MODEL (self->origin_store); g_assert (CALLS_IS_ORIGIN (item));
GtkTreeIter iter;
if (!gtk_tree_model_get_iter_first (origin_store, &iter)) return g_strdup (calls_origin_get_name (item));
{ }
gtk_widget_hide (GTK_WIDGET (self->origin_box));
gtk_widget_set_sensitive (GTK_WIDGET (self->dial), FALSE);
return;
}
/* 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)) origins = calls_manager_get_origins (calls_manager_get_default ());
{ n_items = g_list_model_get_n_items (origins);
gtk_combo_box_set_active (self->origin_box, 0);
gtk_widget_hide (GTK_WIDGET (self->origin_box)); 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 else
{ hdy_combo_row_bind_name_model (self->origin_list,
/* We know there are multiple origins. */ NULL, NULL, NULL, NULL);
if (gtk_combo_box_get_active (self->origin_box) < 0) if (n_items)
{ hdy_combo_row_set_selected_index (self->origin_list, 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));
}
dial_queued (self); dial_queued (self);
} }
static void 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); g_assert (CALLS_IS_NEW_CALL_BOX (self));
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);
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 static void
calls_new_call_box_init (CallsNewCallBox *self) calls_new_call_box_init (CallsNewCallBox *self)
{ {
g_autoptr (GList) origins = NULL;
GList *o;
gtk_widget_init_template (GTK_WIDGET (self)); gtk_widget_init_template (GTK_WIDGET (self));
g_signal_connect_swapped (calls_manager_get_default (), g_signal_connect_swapped (calls_manager_get_default (),
"origin-add", "notify::provider",
G_CALLBACK (add_origin), G_CALLBACK (provider_changed_cb),
self); self);
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);
} }
@ -294,11 +234,6 @@ dispose (GObject *object)
clear_dial_queue (self); clear_dial_queue (self);
if (self->origin_store)
{
remove_origins (self);
}
if (self->long_press_back_gesture != NULL) if (self->long_press_back_gesture != NULL)
g_object_unref (self->long_press_back_gesture); g_object_unref (self->long_press_back_gesture);
@ -315,8 +250,8 @@ calls_new_call_box_class_init (CallsNewCallBoxClass *klass)
object_class->dispose = dispose; object_class->dispose = dispose;
gtk_widget_class_set_template_from_resource (widget_class, "/sm/puri/calls/ui/new-call-box.ui"); 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_list_box);
gtk_widget_class_bind_template_child (widget_class, CallsNewCallBox, origin_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, backspace);
gtk_widget_class_bind_template_child (widget_class, CallsNewCallBox, long_press_back_gesture); gtk_widget_class_bind_template_child (widget_class, CallsNewCallBox, long_press_back_gesture);
gtk_widget_class_bind_template_child (widget_class, CallsNewCallBox, keypad); 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); calls_origin_dial (origin, target);
g_object_unref (origin);
} }
void void

View file

@ -58,13 +58,6 @@ enum {
static GParamSpec *props[PROP_LAST_PROP]; static GParamSpec *props[PROP_LAST_PROP];
enum {
SIGNAL_ORIGIN_ADDED,
SIGNAL_ORIGIN_REMOVED,
SIGNAL_LAST_SIGNAL,
};
static guint signals [SIGNAL_LAST_SIGNAL];
static void static void
calls_provider_get_property (GObject *object, calls_provider_get_property (GObject *object,
guint prop_id, guint prop_id,
@ -99,20 +92,6 @@ calls_provider_class_init (CallsProviderClass *klass)
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (object_class, PROP_LAST_PROP, props); 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 static void
@ -151,10 +130,9 @@ calls_provider_get_status (CallsProvider *self)
* *
* Get the list of #CallsOrigin interfaces offered by this provider. * Get the list of #CallsOrigin interfaces offered by this provider.
* *
* Returns: A newly-allocated GList of objects implementing * Returns: (transfer none): A #GListModel of origins
* #CallsOrigin or NULL if there was an error.
*/ */
GList * GListModel *
calls_provider_get_origins (CallsProvider *self) calls_provider_get_origins (CallsProvider *self)
{ {
g_return_val_if_fail (CALLS_IS_PROVIDER (self), NULL); g_return_val_if_fail (CALLS_IS_PROVIDER (self), NULL);

View file

@ -46,13 +46,13 @@ struct _CallsProviderClass
const char *(*get_name) (CallsProvider *self); const char *(*get_name) (CallsProvider *self);
const char *(*get_status) (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_name (CallsProvider *self);
const char *calls_provider_get_status (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 G_END_DECLS

View file

@ -21,26 +21,19 @@
<property name="orientation">vertical</property> <property name="orientation">vertical</property>
<property name="valign">center</property> <property name="valign">center</property>
<property name="visible">True</property> <property name="visible">True</property>
<child> <child>
<object class="GtkComboBox" id="origin_box"> <object class="GtkListBox" id="origin_list_box">
<property name="can_focus">False</property>
<property name="model">origin_store</property>
<property name="id_column">0</property>
<property name="margin_bottom">8</property>
<property name="no_show_all">True</property>
<property name="visible">True</property> <property name="visible">True</property>
<property name="selection-mode">none</property>
<child> <child>
<object class="GtkCellRendererText"/> <object class="HdyComboRow" id="origin_list">
<attributes> <property name="visible">True</property>
<attribute name="text">0</attribute> </object>
</attributes>
</child> </child>
</object> </object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkBox"> <object class="GtkBox">
<property name="visible">True</property> <property name="visible">True</property>

View file

@ -11,7 +11,7 @@ void
test_dummy_origin_set_up (OriginFixture *fixture, test_dummy_origin_set_up (OriginFixture *fixture,
gconstpointer user_data) gconstpointer user_data)
{ {
GList *origins; GListModel *origins;
test_dummy_provider_set_up (&fixture->parent, user_data); 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 origins = calls_provider_get_origins
(CALLS_PROVIDER (fixture->parent.dummy_provider)); (CALLS_PROVIDER (fixture->parent.dummy_provider));
fixture->dummy_origin = CALLS_DUMMY_ORIGIN (origins->data); fixture->dummy_origin = g_list_model_get_item (origins, 0);
g_list_free (origins);
} }

View file

@ -9,21 +9,8 @@
#include <gtk/gtk.h> #include <gtk/gtk.h>
#include <libpeas/peas.h> #include <libpeas/peas.h>
gint origin_count = 0;
CallsCall *test_call = NULL; CallsCall *test_call = NULL;
static void
origin_add_cb (CallsManager *manager)
{
origin_count++;
}
static void
origin_remove_cb (CallsManager *manager)
{
origin_count--;
}
static void static void
call_add_cb (CallsManager *manager, CallsCall *call) call_add_cb (CallsManager *manager, CallsCall *call)
{ {
@ -54,36 +41,32 @@ static void
test_calls_manager_dummy_provider () test_calls_manager_dummy_provider ()
{ {
g_autoptr (CallsManager) manager = calls_manager_new (); g_autoptr (CallsManager) manager = calls_manager_new ();
g_autoptr (GList) origins = NULL; GListModel *origins;
gint no_origins = 0;
CallsOrigin *origin; CallsOrigin *origin;
g_assert (CALLS_IS_MANAGER (manager)); 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_null (calls_manager_get_provider (manager));
g_assert (calls_manager_get_state (manager) == CALLS_MANAGER_STATE_NO_PROVIDER); 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"); calls_manager_set_provider (manager, "dummy");
g_assert_cmpstr (calls_manager_get_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 (calls_manager_get_state (manager) == CALLS_MANAGER_STATE_READY);
g_assert_nonnull (calls_manager_get_origins (manager));
origins = 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_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_calls (manager));
g_assert_null (calls_manager_get_default_origin (manager)); g_assert_null (calls_manager_get_default_origin (manager));
test_call = NULL; 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-add", G_CALLBACK (call_add_cb), NULL);
g_signal_connect (manager, "call-remove", G_CALLBACK (call_remove_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)); g_assert (CALLS_IS_ORIGIN (origin));
calls_manager_set_default_origin (manager, origin); calls_manager_set_default_origin (manager, origin);
@ -101,8 +84,8 @@ test_calls_manager_dummy_provider ()
/* Unload the provider */ /* Unload the provider */
calls_manager_set_provider (manager, NULL); calls_manager_set_provider (manager, NULL);
g_assert_cmpint (origin_count, ==, 0);
g_assert_null (test_call); 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); g_assert (calls_manager_get_state (manager) == CALLS_MANAGER_STATE_NO_PROVIDER);
} }

View file

@ -41,12 +41,11 @@ static void
test_dummy_provider_origins (ProviderFixture *fixture, test_dummy_provider_origins (ProviderFixture *fixture,
gconstpointer user_data) gconstpointer user_data)
{ {
GList *origins; GListModel *origins;
origins = calls_provider_get_origins origins = calls_provider_get_origins
(CALLS_PROVIDER (fixture->dummy_provider)); (CALLS_PROVIDER (fixture->dummy_provider));
g_assert_cmpuint (g_list_length (origins), ==, 1); g_assert_cmpuint (g_list_model_get_n_items (origins), ==, 1);
g_list_free (origins);
} }