<commit_before>/*
 * Copyright (C) 2016 <NAME>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

#include "config.h"

#include "sn-dbus-menu-item.h"
#include "sn-image-menu-item.h"

static GdkPixbuf *
pxibuf_new (GVariant *variant)
{
  gsize length;
  const guchar *data;
  GInputStream *stream;
  GdkPixbuf *pixbuf;
  GError *error;

  data = g_variant_get_fixed_array (variant, &length, sizeof (guchar));

  if (length == 0)
    return NULL;

  stream = g_memory_input_stream_new_from_data (data, length, NULL);

  if (stream == NULL)
    return NULL;

  error = NULL;
  pixbuf = gdk_pixbuf_new_from_stream (stream, NULL, &error);
  g_object_unref (stream);

  if (error != NULL)
    {
      g_warning ("Unable to build GdkPixbuf from icon data: %s", error->message);
      g_error_free (error);
    }

  return pixbuf;
}

static SnShortcut *
sn_shortcut_new (guint           key,
                 GdkModifierType mask)
{
  SnShortcut *shortcut;

  shortcut = g_new0 (SnShortcut, 1);

  shortcut->key = key;
  shortcut->mask = mask;

  return shortcut;
}

static SnShortcut **
sn_shortcuts_new (GVariant *variant)
{
  GPtrArray *array;
  GVariantIter shortcuts;
  GVariantIter *shortcut;

  if (variant == NULL || g_variant_iter_init (&shortcuts, variant) == 0)
    return NULL;

  array = g_ptr_array_new ();
  while (g_variant_iter_next (&shortcuts, "as", &shortcut))
    {
      guint key;
      GdkModifierType mask;
      const gchar *string;

      key = 0;
      mask = 0;

      while (g_variant_iter_next (shortcut, "&s", &string))
        {
          if (g_strcmp0 (string, "Control") == 0)
            mask |= GDK_CONTROL_MASK;
          else if (g_strcmp0 (string, "Alt") == 0)
            mask |= GDK_MOD1_MASK;
          else if (g_strcmp0 (string, "Shift") == 0)
            mask |= GDK_SHIFT_MASK;
          else if (g_strcmp0 (string, "Super") == 0)
            mask |= GDK_SUPER_MASK;
          else
            gtk_accelerator_parse (string, &key, NULL);
        }

      g_ptr_array_add (array,sn_shortcut_new (key, mask));
      g_variant_iter_free (shortcut);
    }

  g_ptr_array_add (array, NULL);
  return (SnShortcut **) g_ptr_array_free (array, FALSE);
}

static void
sn_shortcuts_free (SnShortcut **shortcuts)
{
  guint i;

  if (shortcuts == NULL)
    return;

  for (i = 0; shortcuts[i] != NULL; i++)
    g_free (shortcuts[i]);

  g_free (shortcuts);
}

SnDBusMenuItem *
sn_dbus_menu_item_new (GVariant *props)
{
  SnDBusMenuItem *item;
  GVariantIter iter;
  const gchar *prop;
  GVariant *value;

  item = g_new0 (SnDBusMenuItem, 1);

  item->enabled = TRUE;
  item->toggle_state = -1;
  item->visible = TRUE;

  g_variant_iter_init (&iter, props);
  while (g_variant_iter_next (&iter, "{&sv}", &prop, &value))
    {
      if (g_strcmp0 (prop, "accessible-desc") == 0)
        item->accessible_desc = g_variant_dup_string (value, NULL);
      else if (g_strcmp0 (prop, "children-display") == 0)
        item->children_display = g_variant_dup_string (value, NULL);
      else if (g_strcmp0 (prop, "disposition") == 0)
        item->disposition = g_variant_dup_string (value, NULL);
      else if (g_strcmp0 (prop, "enabled") == 0)
        item->enabled = g_variant_get_boolean (value);
      else if (g_strcmp0 (prop, "icon-name") == 0)
        item->icon_name = g_variant_dup_string (value, NULL);
      else if (g_strcmp0 (prop, "icon-data") == 0)
        item->icon_data = pxibuf_new (value);
      else if (g_strcmp0 (prop, "label") == 0)
        item->label = g_variant_dup_string (value, NULL);
      else if (g_strcmp0 (prop, "shortcut") == 0)
        item->shortcuts = sn_shortcuts_new (value);
      else if (g_strcmp0 (prop, "toggle-type") == 0)
        item->toggle_type = g_variant_dup_string (value, NULL);
      else if (g_strcmp0 (prop, "toggle-state") == 0)
        item->toggle_state = g_variant_get_int32 (value);
      else if (g_strcmp0 (prop, "type") == 0)
        item->type = g_variant_dup_string (value, NULL);
      else if (g_strcmp0 (prop, "visible") == 0)
        item->visible = g_variant_get_boolean (value);
      else
        g_debug ("unknown property '%s'", prop);

      g_variant_unref (value);
    }

  if (g_strcmp0 (item->type, "separator") == 0)
    {
      item->item = gtk_separator_menu_item_new ();
    }
  else
    {
      if (g_strcmp0 (item->toggle_type, "checkmark") == 0)
        {
          item->item = gtk_check_menu_item_new ();
          gtk_menu_item_set_use_underline (GTK_MENU_ITEM (item->item), TRUE);
        }
      else if (g_strcmp0 (item->toggle_type, "radio") == 0)
        {
          item->item = gtk_radio_menu_item_new (NULL);
          gtk_menu_item_set_use_underline (GTK_MENU_ITEM (item->item), TRUE);
        }
      else
        {
          SnImageMenuItem *image_item;

          item->item = sn_image_menu_item_new ();
          image_item = SN_IMAGE_MENU_ITEM (item->item);

          if (item->icon_name)
            {
              sn_image_menu_item_set_image_from_icon_name (image_item,
                                                           item->icon_name);
            }
          else if (item->icon_data)
            {<commit_msg>status-notifier: fix dbus radio menu items<commit_after>/*
 * Copyright (C) 2016 <NAME>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

#include "config.h"

#include "sn-dbus-menu-item.h"
#include "sn-image-menu-item.h"

static GdkPixbuf *
pxibuf_new (GVariant *variant)
{
  gsize length;
  const guchar *data;
  GInputStream *stream;
  GdkPixbuf *pixbuf;
  GError *error;

  data = g_variant_get_fixed_array (variant, &length, sizeof (guchar));

  if (length == 0)
    return NULL;

  stream = g_memory_input_stream_new_from_data (data, length, NULL);

  if (stream == NULL)
    return NULL;

  error = NULL;
  pixbuf = gdk_pixbuf_new_from_stream (stream, NULL, &error);
  g_object_unref (stream);

  if (error != NULL)
    {
      g_warning ("Unable to build GdkPixbuf from icon data: %s", error->message);
      g_error_free (error);
    }

  return pixbuf;
}

static SnShortcut *
sn_shortcut_new (guint           key,
                 GdkModifierType mask)
{
  SnShortcut *shortcut;

  shortcut = g_new0 (SnShortcut, 1);

  shortcut->key = key;
  shortcut->mask = mask;

  return shortcut;
}

static SnShortcut **
sn_shortcuts_new (GVariant *variant)
{
  GPtrArray *array;
  GVariantIter shortcuts;
  GVariantIter *shortcut;

  if (variant == NULL || g_variant_iter_init (&shortcuts, variant) == 0)
    return NULL;

  array = g_ptr_array_new ();
  while (g_variant_iter_next (&shortcuts, "as", &shortcut))
    {
      guint key;
      GdkModifierType mask;
      const gchar *string;

      key = 0;
      mask = 0;

      while (g_variant_iter_next (shortcut, "&s", &string))
        {
          if (g_strcmp0 (string, "Control") == 0)
            mask |= GDK_CONTROL_MASK;
          else if (g_strcmp0 (string, "Alt") == 0)
            mask |= GDK_MOD1_MASK;
          else if (g_strcmp0 (string, "Shift") == 0)
            mask |= GDK_SHIFT_MASK;
          else if (g_strcmp0 (string, "Super") == 0)
            mask |= GDK_SUPER_MASK;
          else
            gtk_accelerator_parse (string, &key, NULL);
        }

      g_ptr_array_add (array,sn_shortcut_new (key, mask));
      g_variant_iter_free (shortcut);
    }

  g_ptr_array_add (array, NULL);
  return (SnShortcut **) g_ptr_array_free (array, FALSE);
}

static void
sn_shortcuts_free (SnShortcut **shortcuts)
{
  guint i;

  if (shortcuts == NULL)
    return;

  for (i = 0; shortcuts[i] != NULL; i++)
    g_free (shortcuts[i]);

  g_free (shortcuts);
}

SnDBusMenuItem *
sn_dbus_menu_item_new (GVariant *props)
{
  SnDBusMenuItem *item;
  GVariantIter iter;
  const gchar *prop;
  GVariant *value;

  item = g_new0 (SnDBusMenuItem, 1);

  item->enabled = TRUE;
  item->toggle_state = -1;
  item->visible = TRUE;

  g_variant_iter_init (&iter, props);
  while (g_variant_iter_next (&iter, "{&sv}", &prop, &value))
    {
      if (g_strcmp0 (prop, "accessible-desc") == 0)
        item->accessible_desc = g_variant_dup_string (value, NULL);
      else if (g_strcmp0 (prop, "children-display") == 0)
        item->children_display = g_variant_dup_string (value, NULL);
      else if (g_strcmp0 (prop, "disposition") == 0)
        item->disposition = g_variant_dup_string (value, NULL);
      else if (g_strcmp0 (prop, "enabled") == 0)
        item->enabled = g_variant_get_boolean (value);
      else if (g_strcmp0 (prop, "icon-name") == 0)
        item->icon_name = g_variant_dup_string (value, NULL);
      else if (g_strcmp0 (prop, "icon-data") == 0)
        item->icon_data = pxibuf_new (value);
      else if (g_strcmp0 (prop, "label") == 0)
        item->label = g_variant_dup_string (value, NULL);
      else if (g_strcmp0 (prop, "shortcut") == 0)
        item->shortcuts = sn_shortcuts_new (value);
      else if (g_strcmp0 (prop, "toggle-type") == 0)
        item->toggle_type = g_variant_dup_string (value, NULL);
      else if (g_strcmp0 (prop, "toggle-state") == 0)
        item->toggle_state = g_variant_get_int32 (value);
      else if (g_strcmp0 (prop, "type") == 0)
        item->type = g_variant_dup_string (value, NULL);
      else if (g_strcmp0 (prop, "visible") == 0)
        item->visible = g_variant_get_boolean (value);
      else
        g_debug ("unknown property '%s'", prop);

      g_variant_unref (value);
    }

  if (g_strcmp0 (item->type, "separator") == 0)
    {
      item->item = gtk_separator_menu_item_new ();
    }
  else
    {
      if (g_strcmp0 (item->toggle_type, "checkmark") == 0)
        {
          item->item = gtk_check_menu_item_new ();
          gtk_menu_item_set_use_underline (GTK_MENU_ITEM (item->item), TRUE);
        }
      else if (g_strcmp0 (item->toggle_type, "radio") == 0)
        {
          AtkObject *accessible;

          item->item = gtk_check_menu_item_new ();
          gtk_check_menu_item_set_draw_as_radio (GTK_CHECK_MENU_ITEM (item->item), TRUE);
          gtk_menu_item_set_use_underline (GTK_MENU_ITEM (item->item), TRUE);

          accessible = gtk_widget_get_accessible (item->item);
          atk_object_set_role (accessible, ATK_ROLE_RADIO_MENU_ITEM);
        }
      else
        {
          SnImageMenuItem *image_item;

          item->item = sn_image_menu_item_new ();
          image_item = SN_IMAGE_MENU_ITEM (item->item);

          if (item->icon_name)
            {
              sn_image_menu_item_set_image_from_icon_name (image_item,
                                                           item->icon_name);
            }
          else if (item->icon_data)
            {
{'fraction_non_alphanumeric': 0.11907386990077178, 'fraction_numerical': 0.009498770248494614, 'mean_word_length': 2.7578075207138304, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 71, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5385153', 'n_tokens_mistral': 4108, 'n_tokens_neox': 3968, 'n_words': 1032}