office-gobmx/vcl/unx/gtk3/gloactiongroup.cxx
Caolán McNamara 2dbf36132a rename to remove the gtk3 prefix
Change-Id: I219798ed42aff11d09fd45c26ca1a018c2d22c08
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/115239
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
2021-05-10 10:56:58 +02:00

405 lines
12 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include <unx/gtk/gtksalmenu.hxx>
#include <unx/gtk/gloactiongroup.h>
#include <sal/log.hxx>
/*
* GLOAction
*/
#define G_TYPE_LO_ACTION (g_lo_action_get_type ())
#define G_LO_ACTION(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), \
G_TYPE_LO_ACTION, GLOAction))
namespace {
struct GLOAction
{
GObject parent_instance;
gint item_id; // Menu item ID.
bool submenu; // TRUE if action is a submenu action.
bool enabled; // TRUE if action is enabled.
GVariantType* parameter_type; // A GVariantType with the action parameter type.
GVariantType* state_type; // A GVariantType with item state type
GVariant* state_hint; // A GVariant with state hints.
GVariant* state; // A GVariant with current item state
};
}
typedef GObjectClass GLOActionClass;
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-function"
#if defined __clang__
#if __has_warning("-Wdeprecated-volatile")
#pragma clang diagnostic ignored "-Wdeprecated-volatile"
#endif
#endif
#endif
G_DEFINE_TYPE (GLOAction, g_lo_action, G_TYPE_OBJECT);
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
static GLOAction*
g_lo_action_new()
{
return G_LO_ACTION (g_object_new (G_TYPE_LO_ACTION, nullptr));
}
static void
g_lo_action_init (GLOAction *action)
{
action->item_id = -1;
action->submenu = false;
action->enabled = true;
action->parameter_type = nullptr;
action->state_type = nullptr;
action->state_hint = nullptr;
action->state = nullptr;
}
static void
g_lo_action_finalize (GObject *object)
{
GLOAction* action = G_LO_ACTION(object);
if (action->parameter_type)
g_variant_type_free (action->parameter_type);
if (action->state_type)
g_variant_type_free (action->state_type);
if (action->state_hint)
g_variant_unref (action->state_hint);
if (action->state)
g_variant_unref (action->state);
G_OBJECT_CLASS (g_lo_action_parent_class)->finalize (object);
}
static void
g_lo_action_class_init (GLOActionClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS(klass);
object_class->finalize = g_lo_action_finalize;
}
/*
* GLOActionGroup
*/
struct GLOActionGroupPrivate
{
GHashTable *table; /* string -> GLOAction */
};
static void g_lo_action_group_iface_init (GActionGroupInterface *);
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-function"
#if defined __clang__
#if __has_warning("-Wdeprecated-volatile")
#pragma clang diagnostic ignored "-Wdeprecated-volatile"
#endif
#endif
#endif
G_DEFINE_TYPE_WITH_CODE (GLOActionGroup,
g_lo_action_group, G_TYPE_OBJECT,
G_ADD_PRIVATE(GLOActionGroup)
G_IMPLEMENT_INTERFACE (G_TYPE_ACTION_GROUP,
g_lo_action_group_iface_init));
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
static gchar **
g_lo_action_group_list_actions (GActionGroup *group)
{
GLOActionGroup *loGroup = G_LO_ACTION_GROUP (group);
GHashTableIter iter;
gint n, i = 0;
gchar **keys;
gpointer key;
n = g_hash_table_size (loGroup->priv->table);
keys = g_new (gchar *, n + 1);
g_hash_table_iter_init (&iter, loGroup->priv->table);
while (g_hash_table_iter_next (&iter, &key, nullptr))
keys[i++] = g_strdup (static_cast<gchar*>(key));
g_assert_cmpint (i, ==, n);
keys[n] = nullptr;
return keys;
}
static gboolean
g_lo_action_group_query_action (GActionGroup *group,
const gchar *action_name,
gboolean *enabled,
const GVariantType **parameter_type,
const GVariantType **state_type,
GVariant **state_hint,
GVariant **state)
{
//SAL_INFO("vcl.unity", "g_lo_action_group_query_action on " << group);
GLOActionGroup *lo_group = G_LO_ACTION_GROUP (group);
GLOAction* action = G_LO_ACTION (g_hash_table_lookup (lo_group->priv->table, action_name));
if (action == nullptr)
return FALSE;
if (enabled)
{
*enabled = action->enabled;
}
if (parameter_type)
*parameter_type = action->parameter_type;
if (state_type)
*state_type = action->state_type;
if (state_hint)
*state_hint = (action->state_hint) ? g_variant_ref (action->state_hint) : nullptr;
if (state)
*state = (action->state) ? g_variant_ref (action->state) : nullptr;
return true;
}
static void
g_lo_action_group_perform_submenu_action (GLOActionGroup *group,
const gchar *action_name,
GVariant *state)
{
bool bState = g_variant_get_boolean (state);
SAL_INFO("vcl.unity", "g_lo_action_group_perform_submenu_action on " << group << " to " << bState);
if (bState)
GtkSalMenu::Activate(action_name);
else
GtkSalMenu::Deactivate(action_name);
}
static void
g_lo_action_group_change_state (GActionGroup *group,
const gchar *action_name,
GVariant *value)
{
SAL_INFO("vcl.unity", "g_lo_action_group_change_state on " << group );
g_return_if_fail (value != nullptr);
g_variant_ref_sink (value);
if (action_name != nullptr)
{
GLOActionGroup* lo_group = G_LO_ACTION_GROUP (group);
GLOAction* action = G_LO_ACTION (g_hash_table_lookup (lo_group->priv->table, action_name));
if (action != nullptr)
{
if (action->submenu)
g_lo_action_group_perform_submenu_action (lo_group, action_name, value);
else
{
bool is_new = false;
/* If action already exists but has no state, it should be removed and added again. */
if (action->state_type == nullptr)
{
g_action_group_action_removed (G_ACTION_GROUP (group), action_name);
action->state_type = g_variant_type_copy (g_variant_get_type(value));
is_new = true;
}
if (g_variant_is_of_type (value, action->state_type))
{
if (action->state)
g_variant_unref(action->state);
action->state = g_variant_ref (value);
if (is_new)
g_action_group_action_added (G_ACTION_GROUP (group), action_name);
else
g_action_group_action_state_changed (group, action_name, value);
}
}
}
}
g_variant_unref (value);
}
static void
g_lo_action_group_activate (GActionGroup *group,
const gchar *action_name,
GVariant *parameter)
{
if (parameter != nullptr)
g_action_group_change_action_state(group, action_name, parameter);
GtkSalMenu::DispatchCommand(action_name);
}
void
g_lo_action_group_insert (GLOActionGroup *group,
const gchar *action_name,
gint item_id,
gboolean submenu)
{
g_lo_action_group_insert_stateful (group, action_name, item_id, submenu, nullptr, nullptr, nullptr, nullptr);
}
void
g_lo_action_group_insert_stateful (GLOActionGroup *group,
const gchar *action_name,
gint item_id,
gboolean submenu,
const GVariantType *parameter_type,
const GVariantType *state_type,
GVariant *state_hint,
GVariant *state)
{
g_return_if_fail (G_IS_LO_ACTION_GROUP (group));
GLOAction* old_action = G_LO_ACTION (g_hash_table_lookup (group->priv->table, action_name));
if (old_action != nullptr && old_action->item_id == item_id)
return;
if (old_action != nullptr)
g_lo_action_group_remove (group, action_name);
GLOAction* action = g_lo_action_new();
g_hash_table_insert (group->priv->table, g_strdup (action_name), action);
action->item_id = item_id;
action->submenu = submenu;
if (parameter_type)
action->parameter_type = const_cast<GVariantType*>(parameter_type);
if (state_type)
action->state_type = const_cast<GVariantType*>(state_type);
if (state_hint)
action->state_hint = g_variant_ref_sink (state_hint);
if (state)
action->state = g_variant_ref_sink (state);
g_action_group_action_added (G_ACTION_GROUP (group), action_name);
}
static void
g_lo_action_group_finalize (GObject *object)
{
GLOActionGroup *lo_group = G_LO_ACTION_GROUP (object);
g_hash_table_unref (lo_group->priv->table);
G_OBJECT_CLASS (g_lo_action_group_parent_class)->finalize (object);
}
static void
g_lo_action_group_init (GLOActionGroup *group)
{
SAL_INFO("vcl.unity", "g_lo_action_group_init on " << group);
group->priv = static_cast<GLOActionGroupPrivate *>(g_lo_action_group_get_instance_private (group));
group->priv->table = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, g_object_unref);
}
static void
g_lo_action_group_class_init (GLOActionGroupClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = g_lo_action_group_finalize;
}
static void
g_lo_action_group_iface_init (GActionGroupInterface *iface)
{
iface->list_actions = g_lo_action_group_list_actions;
iface->query_action = g_lo_action_group_query_action;
iface->change_action_state = g_lo_action_group_change_state;
iface->activate_action = g_lo_action_group_activate;
}
GLOActionGroup *
g_lo_action_group_new()
{
GLOActionGroup* group = G_LO_ACTION_GROUP (g_object_new (G_TYPE_LO_ACTION_GROUP, nullptr));
return group;
}
void
g_lo_action_group_set_action_enabled (GLOActionGroup *group,
const gchar *action_name,
gboolean enabled)
{
SAL_INFO("vcl.unity", "g_lo_action_group_set_action_enabled on " << group);
g_return_if_fail (G_IS_LO_ACTION_GROUP (group));
g_return_if_fail (action_name != nullptr);
GLOAction* action = G_LO_ACTION (g_hash_table_lookup (group->priv->table, action_name));
if (action == nullptr)
return;
action->enabled = enabled;
g_action_group_action_enabled_changed (G_ACTION_GROUP (group), action_name, enabled);
}
void
g_lo_action_group_remove (GLOActionGroup *group,
const gchar *action_name)
{
SAL_INFO("vcl.unity", "g_lo_action_group_remove on " << group);
g_return_if_fail (G_IS_LO_ACTION_GROUP (group));
if (action_name != nullptr)
{
g_action_group_action_removed (G_ACTION_GROUP (group), action_name);
g_hash_table_remove (group->priv->table, action_name);
}
}
void
g_lo_action_group_clear (GLOActionGroup *group)
{
SAL_INFO("vcl.unity", "g_lo_action_group_clear on " << group);
g_return_if_fail (G_IS_LO_ACTION_GROUP (group));
GList* keys = g_hash_table_get_keys (group->priv->table);
for (GList* element = g_list_first (keys); element != nullptr; element = g_list_next (element))
{
g_lo_action_group_remove (group, static_cast<gchar*>(element->data));
}
g_list_free (keys);
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */