libsysprof-gtk: improve session model robustness

Handle items-changed, ensure we calculate items-changed at setup time
correctly when late binding is in use.
This commit is contained in:
Christian Hergert
2023-07-14 12:20:13 -07:00
parent 15df36f6c2
commit 1ad6f66b9e

View File

@ -27,6 +27,7 @@ struct _SysprofSessionModel
{ {
GObject parent_instance; GObject parent_instance;
GListModel *model; GListModel *model;
GSignalGroup *model_signals;
SysprofSession *session; SysprofSession *session;
}; };
@ -67,7 +68,7 @@ sysprof_session_model_get_n_items (GListModel *model)
{ {
SysprofSessionModel *self = SYSPROF_SESSION_MODEL (model); SysprofSessionModel *self = SYSPROF_SESSION_MODEL (model);
if (self->model == NULL) if (self->model == NULL || self->session == 0)
return 0; return 0;
return g_list_model_get_n_items (self->model); return g_list_model_get_n_items (self->model);
@ -86,11 +87,27 @@ G_DEFINE_FINAL_TYPE_WITH_CODE (SysprofSessionModel, sysprof_session_model, G_TYP
static GParamSpec *properties [N_PROPS]; static GParamSpec *properties [N_PROPS];
static void
sysprof_session_model_items_changed_cb (SysprofSessionModel *self,
guint position,
guint removed,
guint added,
GListModel *model)
{
g_assert (SYSPROF_IS_SESSION_MODEL (self));
if (self->session == NULL || self->model != model)
return;
g_list_model_items_changed (G_LIST_MODEL (self), position, removed, added);
}
static void static void
sysprof_session_model_dispose (GObject *object) sysprof_session_model_dispose (GObject *object)
{ {
SysprofSessionModel *self = (SysprofSessionModel *)object; SysprofSessionModel *self = (SysprofSessionModel *)object;
g_clear_object (&self->model_signals);
g_clear_object (&self->session); g_clear_object (&self->session);
g_clear_object (&self->model); g_clear_object (&self->model);
@ -168,6 +185,12 @@ sysprof_session_model_class_init (SysprofSessionModelClass *klass)
static void static void
sysprof_session_model_init (SysprofSessionModel *self) sysprof_session_model_init (SysprofSessionModel *self)
{ {
self->model_signals = g_signal_group_new (G_TYPE_LIST_MODEL);
g_signal_group_connect_object (self->model_signals,
"items-changed",
G_CALLBACK (sysprof_session_model_items_changed_cb),
self,
G_CONNECT_SWAPPED);
} }
SysprofSessionModel * SysprofSessionModel *
@ -201,8 +224,8 @@ void
sysprof_session_model_set_model (SysprofSessionModel *self, sysprof_session_model_set_model (SysprofSessionModel *self,
GListModel *model) GListModel *model)
{ {
guint old_len = 0; guint old_n_items = 0;
guint new_len = 0; guint new_n_items = 0;
g_return_if_fail (SYSPROF_IS_SESSION_MODEL (self)); g_return_if_fail (SYSPROF_IS_SESSION_MODEL (self));
g_return_if_fail (!model || G_IS_LIST_MODEL (model)); g_return_if_fail (!model || G_IS_LIST_MODEL (model));
@ -210,22 +233,18 @@ sysprof_session_model_set_model (SysprofSessionModel *self,
if (self->model == model) if (self->model == model)
return; return;
if (self->model)
{
old_len = g_list_model_get_n_items (G_LIST_MODEL (self->model));
g_clear_object (&self->model);
}
if (model) if (model)
{ g_object_ref (model);
self->model = g_object_ref (model);
new_len = g_list_model_get_n_items (model); old_n_items = g_list_model_get_n_items (G_LIST_MODEL (self));
} g_set_object (&self->model, model);
g_signal_group_set_target (self->model_signals, model);
new_n_items = g_list_model_get_n_items (G_LIST_MODEL (self));
if (old_n_items || new_n_items)
g_list_model_items_changed (G_LIST_MODEL (self), 0, old_n_items, new_n_items);
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_MODEL]); g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_MODEL]);
if (old_len || new_len)
g_list_model_items_changed (G_LIST_MODEL (self), 0, old_len, new_len);
} }
/** /**
@ -246,16 +265,21 @@ void
sysprof_session_model_set_session (SysprofSessionModel *self, sysprof_session_model_set_session (SysprofSessionModel *self,
SysprofSession *session) SysprofSession *session)
{ {
guint old_n_items = 0;
guint new_n_items = 0;
g_return_if_fail (SYSPROF_IS_SESSION_MODEL (self)); g_return_if_fail (SYSPROF_IS_SESSION_MODEL (self));
g_return_if_fail (!session || SYSPROF_IS_SESSION (session)); g_return_if_fail (!session || SYSPROF_IS_SESSION (session));
if (g_set_object (&self->session, session)) if (self->session == session)
{ return;
guint n_items = g_list_model_get_n_items (G_LIST_MODEL (self));
if (n_items > 0) old_n_items = g_list_model_get_n_items (G_LIST_MODEL (self));
g_list_model_items_changed (G_LIST_MODEL (self), 0, n_items, n_items); g_set_object (&self->session, session);
new_n_items = g_list_model_get_n_items (G_LIST_MODEL (self));
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SESSION]); if (old_n_items || new_n_items)
} g_list_model_items_changed (G_LIST_MODEL (self), 0, old_n_items, new_n_items);
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SESSION]);
} }