gnome: bind to the UserActionModel
GActions call the UserActionModel and the UAM
updates the state of the GActions. This also
solves the problem of the unsyced hold action.
Refs #67159
Change-Id: I70900888deb51275decdff19607a846b191b24d1
diff --git a/src/ring_client.cpp b/src/ring_client.cpp
index 31a512a..c96de19 100644
--- a/src/ring_client.cpp
+++ b/src/ring_client.cpp
@@ -146,62 +146,11 @@
return 0;
}
-static void
-call_accept(G_GNUC_UNUSED GSimpleAction *action, G_GNUC_UNUSED GVariant *param, G_GNUC_UNUSED gpointer client)
-{
- g_debug("call accpet action");
-
- /* TODO: implement using UserActionModel once its fixed */
-
- QModelIndex idx = CallModel::instance()->selectionModel()->currentIndex();
- if (idx.isValid()) {
- Call *call = CallModel::instance()->getCall(idx);
- call->performAction(Call::Action::ACCEPT);
- }
-}
-
-static void
-call_hangup(G_GNUC_UNUSED GSimpleAction *action, G_GNUC_UNUSED GVariant *param, G_GNUC_UNUSED gpointer client)
-{
- g_debug("call hangup action");
-
- /* TODO: implement using UserActionModel once its fixed */
-
- QModelIndex idx = CallModel::instance()->selectionModel()->currentIndex();
- if (idx.isValid()) {
- Call *call = CallModel::instance()->getCall(idx);
- call->performAction(Call::Action::REFUSE);
- }
-}
-
-static void
-call_hold(GSimpleAction *action, GVariant *state, G_GNUC_UNUSED gpointer data)
-{
- g_debug("call hold action");
-
- /* TODO: implement using UserActionModel once its fixed */
-
- /* get the requested state and apply it */
- gboolean requested = g_variant_get_boolean(state);
- g_simple_action_set_state(action, g_variant_new_boolean(requested));
-
- QModelIndex idx = CallModel::instance()->selectionModel()->currentIndex();
- if (idx.isValid()) {
- Call *call = CallModel::instance()->getCall(idx);
- call->performAction(Call::Action::HOLD);
- }
-}
-
-/* starting glib 2.40 the action() parameter in the action entry (the second one)
- * can be left NULL for stateful boolean actions and they will automatically be
- * toggled; for older versions of glib we must explicitly set a handler to toggle them */
-#if GLIB_CHECK_VERSION(2,40,0)
-
static const GActionEntry ring_actions[] =
{
- { "accept", call_accept, NULL, NULL, NULL, {0} },
- { "hangup", call_hangup, NULL, NULL, NULL, {0} },
- { "hold", NULL, NULL, "false", call_hold, {0} },
+ { "accept", NULL, NULL, NULL, NULL, {0} },
+ { "hangup", NULL, NULL, NULL, NULL, {0} },
+ { "hold", NULL, NULL, "false", NULL, {0} },
/* TODO implement the other actions */
// { "mute_audio", NULL, NULL, "false", NULL, {0} },
// { "mute_video", NULL, NULL, "false", NULL, {0} },
@@ -209,76 +158,7 @@
// { "record", NULL, NULL, "false", NULL, {0} }
};
-#else
-
-/* adapted from glib 2.40, gsimpleaction.c */
-static void
-g_simple_action_change_state(GSimpleAction *simple, GVariant *value)
-{
- GAction *action = G_ACTION(simple);
-
- guint change_state_id = g_signal_lookup("change-state", G_OBJECT_TYPE(simple));
-
- /* If the user connected a signal handler then they are responsible
- * for handling state changes.
- */
- if (g_signal_has_handler_pending(action, change_state_id, 0, TRUE))
- g_signal_emit(action, change_state_id, 0, value);
-
- /* If not, then the default behaviour is to just set the state. */
- else
- g_simple_action_set_state(simple, value);
-}
-
-/* define activate handler for simple toggle actions for glib < 2.40
- * adapted from glib 2.40, gsimpleaction.c */
-static void
-g_simple_action_toggle(GSimpleAction *action, GVariant *parameter, G_GNUC_UNUSED gpointer user_data)
-{
- const GVariantType *parameter_type = g_action_get_parameter_type(G_ACTION(action));
- g_return_if_fail(parameter_type == NULL ?
- parameter == NULL :
- (parameter != NULL &&
- g_variant_is_of_type(parameter, parameter_type)));
-
- if (parameter != NULL)
- g_variant_ref_sink(parameter);
-
- if (g_action_get_enabled(G_ACTION(action))) {
- /* make sure it is a stateful action and toggle it */
- GVariant *state = g_action_get_state(G_ACTION(action));
- if (state) {
- /* If we have no parameter and this is a boolean action, toggle. */
- if (parameter == NULL && g_variant_is_of_type(state, G_VARIANT_TYPE_BOOLEAN)) {
- gboolean was_enabled = g_variant_get_boolean(state);
- g_simple_action_change_state(action, g_variant_new_boolean(!was_enabled));
- }
- /* else, if the parameter and state type are the same, do a change-state */
- else if (g_variant_is_of_type (state, g_variant_get_type(parameter)))
- g_simple_action_change_state(action, parameter);
- }
- g_variant_unref(state);
- }
-
- if (parameter != NULL)
- g_variant_unref (parameter);
-}
-
-static const GActionEntry ring_actions[] =
-{
- { "accept", call_accept, NULL, NULL, NULL, {0} },
- { "hangup", call_hangup, NULL, NULL, NULL, {0} },
- { "hold", g_simple_action_toggle, NULL, "false", call_hold, {0} },
- /* TODO implement the other actions */
- // { "mute_audio", NULL, NULL, "false", NULL, {0} },
- // { "mute_video", NULL, NULL, "false", NULL, {0} },
- // { "transfer", NULL, NULL, "flase", NULL, {0} },
- // { "record", NULL, NULL, "false", NULL, {0} }
-};
-
-#endif
-
-/* TODO: uncomment when UserActionModel is fixed and used
+/* this union is used to pass the int refering to the Action as a parameter to the GAction callback */
typedef union _int_ptr_t
{
int value;
@@ -297,7 +177,6 @@
uam << a;
}
-*/
static void
ring_client_startup(GApplication *app)
@@ -309,43 +188,39 @@
g_action_map_add_action_entries(
G_ACTION_MAP(app), ring_actions, G_N_ELEMENTS(ring_actions), client);
- /* TODO: Bind actions to the useractionmodel once it is working */
- // UserActionModel* uam = CallModel::instance()->userActionModel();
- // QHash<int, GSimpleAction*> actionHash;
- // actionHash[ (int)UserActionModel::Action::ACCEPT ] = G_SIMPLE_ACTION(g_action_map_lookup_action(G_ACTION_MAP(app), "accept"));
- // actionHash[ (int)UserActionModel::Action::HOLD ] = G_SIMPLE_ACTION(g_action_map_lookup_action(G_ACTION_MAP(app), "hold"));
- // // actionHash[ (int)UserActionModel::Action::MUTE_AUDIO ] = G_SIMPLE_ACTION(g_action_map_lookup_action(G_ACTION_MAP(app), "mute_audio"));
- // // actionHash[ (int)UserActionModel::Action::SERVER_TRANSFER ] = G_SIMPLE_ACTION(g_action_map_lookup_action(G_ACTION_MAP(app), "transfer"));
- // // actionHash[ (int)UserActionModel::Action::RECORD ] = G_SIMPLE_ACTION(g_action_map_lookup_action(G_ACTION_MAP(app), "record"));
- // actionHash[ (int)UserActionModel::Action::HANGUP ] = G_SIMPLE_ACTION(g_action_map_lookup_action(G_ACTION_MAP(app), "hangup"));
+ /* Bind GActions to the UserActionModel */
+ UserActionModel* uam = CallModel::instance()->userActionModel();
+ QHash<int, GSimpleAction*> actionHash;
+ actionHash[ (int)UserActionModel::Action::ACCEPT ] = G_SIMPLE_ACTION(g_action_map_lookup_action(G_ACTION_MAP(app), "accept"));
+ actionHash[ (int)UserActionModel::Action::HOLD ] = G_SIMPLE_ACTION(g_action_map_lookup_action(G_ACTION_MAP(app), "hold"));
+ /* TODO: add commented actions when ready */
+ // actionHash[ (int)UserActionModel::Action::MUTE_AUDIO ] = G_SIMPLE_ACTION(g_action_map_lookup_action(G_ACTION_MAP(app), "mute_audio"));
+ // actionHash[ (int)UserActionModel::Action::SERVER_TRANSFER ] = G_SIMPLE_ACTION(g_action_map_lookup_action(G_ACTION_MAP(app), "transfer"));
+ // actionHash[ (int)UserActionModel::Action::RECORD ] = G_SIMPLE_ACTION(g_action_map_lookup_action(G_ACTION_MAP(app), "record"));
+ actionHash[ (int)UserActionModel::Action::HANGUP ] = G_SIMPLE_ACTION(g_action_map_lookup_action(G_ACTION_MAP(app), "hangup"));
- // for (QHash<int,GSimpleAction*>::const_iterator i = actionHash.begin(); i != actionHash.end(); ++i) {
- // GSimpleAction* sa = i.value();
- // // UserActionModel::Action a = static_cast<UserActionModel::Action>(i.key());
- // // connect(ea, &QAction::triggered, [uam,a](bool) {uam << a;});
- // int_ptr_t user_data;
- // user_data.value = i.key();
- // g_signal_connect(G_OBJECT(sa), "activate", G_CALLBACK(activate_action), user_data.ptr);
+ for (QHash<int,GSimpleAction*>::const_iterator i = actionHash.begin(); i != actionHash.end(); ++i) {
+ GSimpleAction* sa = i.value();
+ int_ptr_t user_data;
+ user_data.value = i.key();
+ g_signal_connect(G_OBJECT(sa), "activate", G_CALLBACK(activate_action), user_data.ptr);
+ }
- // }
-
- // QObject::connect(uam,&UserActionModel::dataChanged, [actionHash,uam](const QModelIndex& tl, const QModelIndex& br) {
- // const int first(tl.row()),last(br.row());
- // for(int i = first; i <= last;i++) {
- // const QModelIndex& idx = uam->index(i,0);
- // GSimpleAction* sa = actionHash[(int)qvariant_cast<UserActionModel::Action>(idx.data(UserActionModel::Role::ACTION))];
- // if (sa) {
- // // a->setText ( idx.data(Qt::DisplayRole).toString() );
- // // a->setEnabled( idx.flags() & Qt::ItemIsEnabled );
- // g_simple_action_set_enabled(sa, idx.flags() & Qt::ItemIsEnabled);
- // // a->setChecked( idx.data(Qt::CheckStateRole) == Qt::Checked );
- // /* check if statefull action */
- // if (g_action_get_state_type(G_ACTION(sa)) != NULL)
- // g_simple_action_set_state(sa, g_variant_new_boolean(idx.data(Qt::CheckStateRole) == Qt::Checked));
- // // a->setAltIcon( qvariant_cast<QPixmap>(idx.data(Qt::DecorationRole)) );
- // }
- // }
- // });
+ /* change the state of the GActions based on the UserActionModel */
+ QObject::connect(uam,&UserActionModel::dataChanged, [actionHash,uam](const QModelIndex& tl, const QModelIndex& br) {
+ const int first(tl.row()),last(br.row());
+ for(int i = first; i <= last;i++) {
+ const QModelIndex& idx = uam->index(i,0);
+ GSimpleAction* sa = actionHash[(int)qvariant_cast<UserActionModel::Action>(idx.data(UserActionModel::Role::ACTION))];
+ if (sa) {
+ /* enable/disable GAction based on UserActionModel */
+ g_simple_action_set_enabled(sa, idx.flags() & Qt::ItemIsEnabled);
+ /* set the state of the action if its stateful */
+ if (g_action_get_state_type(G_ACTION(sa)) != NULL)
+ g_simple_action_set_state(sa, g_variant_new_boolean(idx.data(Qt::CheckStateRole) == Qt::Checked));
+ }
+ }
+ });
}
static void