<commit_before>#include "iconbrowserapp.h"
#include "iconbrowserwin.h"
#include <gtk/gtk.h>

typedef struct
{
  const gchar *id;
  const gchar *name;
  const gchar *description;
} Context;

struct _IconBrowserWindow
{
  GtkApplicationWindow parent;
  GHashTable *contexts;

  GtkWidget *context_list;
  Context *current_context;
  gboolean symbolic;
  GtkWidget *symbolic_radio;
  GtkTreeModelFilter *filter_model;
  GtkWidget *details;

  GtkListStore *store;
  GtkCellRenderer *cell;
  GtkCellRenderer *text_cell;
  GtkWidget *search;
  GtkWidget *searchbar;
  GtkWidget *searchentry;
  GtkWidget *list;
  GtkWidget *image1;
  GtkWidget *image2;
  GtkWidget *image3;
  GtkWidget *image4;
  GtkWidget *image5;
  GtkWidget *description;
};

struct _IconBrowserWindowClass
{
  GtkApplicationWindowClass parent_class;
};

enum {
  NAME_COLUMN,
  SYMBOLIC_NAME_COLUMN,
  DESCRIPTION_COLUMN,
  CONTEXT_COLUMN
};

G_DEFINE_TYPE(IconBrowserWindow, icon_browser_window, GTK_TYPE_APPLICATION_WINDOW);

static void
search_text_changed (GtkEntry *entry)
{
  const gchar *text;

  text = gtk_entry_get_text (entry);

  if (text[0] == '\0')
    return;
}

static void
set_image (GtkWidget *image, const gchar *name, gint size)
{
  gtk_image_set_from_icon_name (GTK_IMAGE (image), name, 1);
  gtk_image_set_pixel_size (GTK_IMAGE (image), size);
}

static void
selection_changed (GtkIconView *icon_view, IconBrowserWindow *win)
{
}

static void
item_activated (GtkIconView *icon_view, GtkTreePath *path, IconBrowserWindow *win)
{
  GtkTreeIter iter;
  gchar *name;
  gchar *description;
  gint column;

  gtk_tree_model_get_iter (GTK_TREE_MODEL (win->filter_model), &iter, path);

  if (win->symbolic)
    column = SYMBOLIC_NAME_COLUMN;
  else
    column = NAME_COLUMN;
  gtk_tree_model_get (GTK_TREE_MODEL (win->filter_model), &iter,
                      column, &name,
                      DESCRIPTION_COLUMN, &description,
                      -1);
      
  if (name == NULL || !gtk_icon_theme_has_icon (gtk_icon_theme_get_default (), name))
    {
      g_free (description);
      return;
    }

  gtk_window_set_title (GTK_WINDOW (win->details), name);
  set_image (win->image1, name, 16);
  set_image (win->image2, name, 24);
  set_image (win->image3, name, 32);
  set_image (win->image4, name, 48);
  set_image (win->image5, name, 64);
  gtk_label_set_text (GTK_LABEL (win->description), description);

  gtk_window_present (GTK_WINDOW (win->details));

  g_free (name);
  g_free (description);
}

static void
add_icon (IconBrowserWindow *win,
          const gchar       *name,
          const gchar       *description,
          const gchar       *context)
{
  gchar *regular_name;
  gchar *symbolic_name;

  regular_name = g_strdup (name);
  if (!gtk_icon_theme_has_icon (gtk_icon_theme_get_default (), regular_name))
    {
      g_free (regular_name);
      regular_name = NULL;
    }

  symbolic_name = g_strconcat (name, "-symbolic", NULL);
  if (!gtk_icon_theme_has_icon (gtk_icon_theme_get_default (), symbolic_name))
    {
      g_free (symbolic_name);
      symbolic_name = NULL;
    }
  gtk_list_store_insert_with_values (win->store, NULL, -1,
                                     NAME_COLUMN, regular_name,
                                     SYMBOLIC_NAME_COLUMN, symbolic_name,
                                     DESCRIPTION_COLUMN, description,
                                     CONTEXT_COLUMN, context,
                                     -1);
}

static void
add_context (IconBrowserWindow *win,
             const gchar       *id,
             const gchar       *name,
             const gchar       *description)
{
  Context *c;
  GtkWidget *row;

  c = g_new (Context, 1);
  c->id = id;
  c->name = name;
  c->description = description;

  g_hash_table_insert (win->contexts, (gpointer)id, c);

  row = gtk_label_new (name);
  g_object_set_data (G_OBJECT (row), "context", c);
  gtk_widget_show (row);
  g_object_set (row, "margin", 10, NULL);

  gtk_list_box_insert (GTK_LIST_BOX (win->context_list), row, -1);

  if (win->current_context == NULL)
    win->current_context = c;
}

static void
selected_context_changed (GtkListBox *list, IconBrowserWindow *win)
{
  GtkWidget *row;
  GtkWidget *label;

  row = GTK_WIDGET (gtk_list_box_get_selected_row (list));
  label = gtk_bin_get_child (GTK_BIN (row));
  win->current_context = g_object_get_data (G_OBJECT (label), "context");
  gtk_tree_model_filter_refilter (win->filter_model);
}

static void
populate (IconBrowserWindow *win)
{
  add_context (win, "actions", "Actions", "Icons which are generally used in menus and dialogs for interacting with the user.");
  add_icon (win, "action-unavailable", "", "actions"); // missing from spec
  add_icon (win, "address-book-new", "The icon used for the action to create a new address book.", "actions");
  add_icon (win, "application-exit", "The icon used for exiting an application. Typically this is seen in the application's menus as File->Quit.", "actions");
  add_icon (win, "appointment-new", "The icon used for the action to create a new appointment in a calendaring application.", "actions");
  add_icon (win, "bookmark-new", "", "actions"); // missing from spec
  add_icon (win, "call-start", "The icon used for initiating or accepting a call. Should be similar to the standard cellular call pickup icon, a green handset with ear and mouth pieces facing upward.", "actions");
  add_icon (win, "call-stop", "The icon used for stopping a current call. Should be similar to the standard cellular call hangup icon, a red handset with ear and mouth pieces facing downward.", "actions");
  add_icon (win, "content-loading", "", "actions"); // missing from spec<commit_msg>icon-browser: Don't crash on exit<commit_after>#include "iconbrowserapp.h"
#include "iconbrowserwin.h"
#include <gtk/gtk.h>

typedef struct
{
  const gchar *id;
  const gchar *name;
  const gchar *description;
} Context;

struct _IconBrowserWindow
{
  GtkApplicationWindow parent;
  GHashTable *contexts;

  GtkWidget *context_list;
  Context *current_context;
  gboolean symbolic;
  GtkWidget *symbolic_radio;
  GtkTreeModelFilter *filter_model;
  GtkWidget *details;

  GtkListStore *store;
  GtkCellRenderer *cell;
  GtkCellRenderer *text_cell;
  GtkWidget *search;
  GtkWidget *searchbar;
  GtkWidget *searchentry;
  GtkWidget *list;
  GtkWidget *image1;
  GtkWidget *image2;
  GtkWidget *image3;
  GtkWidget *image4;
  GtkWidget *image5;
  GtkWidget *description;
};

struct _IconBrowserWindowClass
{
  GtkApplicationWindowClass parent_class;
};

enum {
  NAME_COLUMN,
  SYMBOLIC_NAME_COLUMN,
  DESCRIPTION_COLUMN,
  CONTEXT_COLUMN
};

G_DEFINE_TYPE(IconBrowserWindow, icon_browser_window, GTK_TYPE_APPLICATION_WINDOW);

static void
search_text_changed (GtkEntry *entry)
{
  const gchar *text;

  text = gtk_entry_get_text (entry);

  if (text[0] == '\0')
    return;
}

static void
set_image (GtkWidget *image, const gchar *name, gint size)
{
  gtk_image_set_from_icon_name (GTK_IMAGE (image), name, 1);
  gtk_image_set_pixel_size (GTK_IMAGE (image), size);
}

static void
selection_changed (GtkIconView *icon_view, IconBrowserWindow *win)
{
}

static void
item_activated (GtkIconView *icon_view, GtkTreePath *path, IconBrowserWindow *win)
{
  GtkTreeIter iter;
  gchar *name;
  gchar *description;
  gint column;

  gtk_tree_model_get_iter (GTK_TREE_MODEL (win->filter_model), &iter, path);

  if (win->symbolic)
    column = SYMBOLIC_NAME_COLUMN;
  else
    column = NAME_COLUMN;
  gtk_tree_model_get (GTK_TREE_MODEL (win->filter_model), &iter,
                      column, &name,
                      DESCRIPTION_COLUMN, &description,
                      -1);
      
  if (name == NULL || !gtk_icon_theme_has_icon (gtk_icon_theme_get_default (), name))
    {
      g_free (description);
      return;
    }

  gtk_window_set_title (GTK_WINDOW (win->details), name);
  set_image (win->image1, name, 16);
  set_image (win->image2, name, 24);
  set_image (win->image3, name, 32);
  set_image (win->image4, name, 48);
  set_image (win->image5, name, 64);
  gtk_label_set_text (GTK_LABEL (win->description), description);

  gtk_window_present (GTK_WINDOW (win->details));

  g_free (name);
  g_free (description);
}

static void
add_icon (IconBrowserWindow *win,
          const gchar       *name,
          const gchar       *description,
          const gchar       *context)
{
  gchar *regular_name;
  gchar *symbolic_name;

  regular_name = g_strdup (name);
  if (!gtk_icon_theme_has_icon (gtk_icon_theme_get_default (), regular_name))
    {
      g_free (regular_name);
      regular_name = NULL;
    }

  symbolic_name = g_strconcat (name, "-symbolic", NULL);
  if (!gtk_icon_theme_has_icon (gtk_icon_theme_get_default (), symbolic_name))
    {
      g_free (symbolic_name);
      symbolic_name = NULL;
    }
  gtk_list_store_insert_with_values (win->store, NULL, -1,
                                     NAME_COLUMN, regular_name,
                                     SYMBOLIC_NAME_COLUMN, symbolic_name,
                                     DESCRIPTION_COLUMN, description,
                                     CONTEXT_COLUMN, context,
                                     -1);
}

static void
add_context (IconBrowserWindow *win,
             const gchar       *id,
             const gchar       *name,
             const gchar       *description)
{
  Context *c;
  GtkWidget *row;

  c = g_new (Context, 1);
  c->id = id;
  c->name = name;
  c->description = description;

  g_hash_table_insert (win->contexts, (gpointer)id, c);

  row = gtk_label_new (name);
  g_object_set_data (G_OBJECT (row), "context", c);
  gtk_widget_show (row);
  g_object_set (row, "margin", 10, NULL);

  gtk_list_box_insert (GTK_LIST_BOX (win->context_list), row, -1);

  if (win->current_context == NULL)
    win->current_context = c;
}

static void
selected_context_changed (GtkListBox *list, IconBrowserWindow *win)
{
  GtkWidget *row;
  GtkWidget *label;

  row = GTK_WIDGET (gtk_list_box_get_selected_row (list));
  if (row == NULL)
    return;

  label = gtk_bin_get_child (GTK_BIN (row));
  win->current_context = g_object_get_data (G_OBJECT (label), "context");
  gtk_tree_model_filter_refilter (win->filter_model);
}

static void
populate (IconBrowserWindow *win)
{
  add_context (win, "actions", "Actions", "Icons which are generally used in menus and dialogs for interacting with the user.");
  add_icon (win, "action-unavailable", "", "actions"); // missing from spec
  add_icon (win, "address-book-new", "The icon used for the action to create a new address book.", "actions");
  add_icon (win, "application-exit", "The icon used for exiting an application. Typically this is seen in the application's menus as File->Quit.", "actions");
  add_icon (win, "appointment-new", "The icon used for the action to create a new appointment in a calendaring application.", "actions");
  add_icon (win, "bookmark-new", "", "actions"); // missing from spec
  add_icon (win, "call-start", "The icon used for initiating or accepting a call. Should be similar to the standard cellular call pickup icon, a green handset with ear and mouth pieces facing upward.", "actions");
  add_icon (win, "call-stop", "The icon used for stopping a current call. Should be similar to the standard cellular call hangup icon, a red handset with ear and mouth pieces facing downward.", "actions");
  add_icon (win, "content-loading", "", "actions"); // missing from spec
{'fraction_non_alphanumeric': 0.10644992134242265, 'fraction_numerical': 0.005243838489774515, 'mean_word_length': 3.515785319652723, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 49, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 10, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4210116', 'n_tokens_mistral': 3951, 'n_tokens_neox': 3808, 'n_words': 1007}