static void
populate_model (GtkListStore *store,
                GtkListStore *active_sources_store)
{
  GHashTable *active_sources_table;
  GtkTreeIter iter;
  const gchar *name;
  GList *sources, *tmp;
  gchar *source_id = NULL;

  active_sources_table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);

  gtk_tree_model_foreach (GTK_TREE_MODEL (active_sources_store),
                          add_source_to_table,
                          active_sources_table);

  sources = gnome_xkb_info_get_all_layouts (xkb_info);

  for (tmp = sources; tmp; tmp = tmp->next)
    {
      g_free (source_id);
      source_id = g_strconcat (INPUT_SOURCE_TYPE_XKB, tmp->data, NULL);

      if (g_hash_table_contains (active_sources_table, source_id))
        continue;

      gnome_xkb_info_get_layout_info (xkb_info, (const gchar *)tmp->data,
                                      &name, NULL, NULL, NULL);

      gtk_list_store_append (store, &iter);
      gtk_list_store_set (store, &iter,
                          NAME_COLUMN, name,
                          TYPE_COLUMN, INPUT_SOURCE_TYPE_XKB,
                          ID_COLUMN, tmp->data,
                          -1);
    }
  g_free (source_id);

  g_list_free (sources);

#ifdef HAVE_IBUS
  if (ibus_engines)
    {
      gchar *display_name;

      sources = g_hash_table_get_keys (ibus_engines);

      source_id = NULL;
      for (tmp = sources; tmp; tmp = tmp->next)
        {
          g_free (source_id);
          source_id = g_strconcat (INPUT_SOURCE_TYPE_IBUS, tmp->data, NULL);

          if (g_hash_table_contains (active_sources_table, source_id))
            continue;

          display_name = engine_get_display_name (g_hash_table_lookup (ibus_engines, tmp->data));

          gtk_list_store_append (store, &iter);
          gtk_list_store_set (store, &iter,
                              NAME_COLUMN, display_name,
                              TYPE_COLUMN, INPUT_SOURCE_TYPE_IBUS,
                              ID_COLUMN, tmp->data,
                              -1);
          g_free (display_name);
        }
      g_free (source_id);

      g_list_free (sources);
    }
#endif

  g_hash_table_destroy (active_sources_table);
}
static void
get_locale_infos (GtkWidget *chooser)
{
  CcInputChooserPrivate *priv = GET_PRIVATE (chooser);
  GHashTable *layouts_with_locale;
  LocaleInfo *info;
  gchar **locale_ids;
  gchar **locale;
  GList *list, *l;

  priv->locales = g_hash_table_new_full (g_str_hash, g_str_equal,
                                         NULL, locale_info_free);
  priv->locales_by_language = g_hash_table_new_full (g_str_hash, g_str_equal,
                                                     g_free, (GDestroyNotify) g_hash_table_destroy);

  layouts_with_locale = g_hash_table_new (g_str_hash, g_str_equal);

  locale_ids = gnome_get_all_locales ();
  for (locale = locale_ids; *locale; ++locale)
    {
      gchar *lang_code, *country_code;
      gchar *simple_locale;
      gchar *tmp;
      const gchar *type = NULL;
      const gchar *id = NULL;

      if (!gnome_parse_locale (*locale, &lang_code, &country_code, NULL, NULL))
        continue;

      if (country_code != NULL)
	simple_locale = g_strdup_printf ("%s_%s.UTF-8", lang_code, country_code);
      else
	simple_locale = g_strdup_printf ("%s.UTF-8", lang_code);

      if (g_hash_table_contains (priv->locales, simple_locale))
        {
          g_free (simple_locale);
          g_free (country_code);
          g_free (lang_code);
          continue;
        }

      info = g_new0 (LocaleInfo, 1);
      info->id = simple_locale; /* Take ownership */
      info->name = gnome_get_language_from_locale (simple_locale, NULL);
      info->unaccented_name = cc_util_normalize_casefold_and_unaccent (info->name);
      tmp = gnome_get_language_from_locale (simple_locale, "C");
      info->untranslated_name = cc_util_normalize_casefold_and_unaccent (tmp);
      g_free (tmp);

      g_hash_table_replace (priv->locales, simple_locale, info);
      add_locale_to_table (priv->locales_by_language, lang_code, info);

      if (gnome_get_input_source_from_locale (simple_locale, &type, &id) &&
          g_str_equal (type, INPUT_SOURCE_TYPE_XKB))
        {
          add_default_row (chooser, info, type, id);
          g_hash_table_add (layouts_with_locale, (gpointer) id);
        }

      /* We don't own these ids */
      info->layout_rows_by_id = g_hash_table_new_full (g_str_hash, g_str_equal,
                                                       NULL, g_object_unref);
      info->engine_rows_by_id = g_hash_table_new_full (g_str_hash, g_str_equal,
                                                       NULL, g_object_unref);

      list = gnome_xkb_info_get_layouts_for_language (priv->xkb_info, lang_code);
      add_rows_to_table (chooser, info, list, INPUT_SOURCE_TYPE_XKB, id);
      add_ids_to_set (layouts_with_locale, list);
      g_list_free (list);

      if (country_code != NULL)
        {
          list = gnome_xkb_info_get_layouts_for_country (priv->xkb_info, country_code);
          add_rows_to_table (chooser, info, list, INPUT_SOURCE_TYPE_XKB, id);
          add_ids_to_set (layouts_with_locale, list);
          g_list_free (list);
        }

      g_free (lang_code);
      g_free (country_code);
    }
  g_strfreev (locale_ids);

  /* Add a "Other" locale to hold the remaining input sources */
  info = g_new0 (LocaleInfo, 1);
  info->id = g_strdup ("");
  info->name = g_strdup (C_("Keyboard Layout", "Other"));
  info->unaccented_name = g_strdup ("");
  info->untranslated_name = g_strdup ("");
  g_hash_table_replace (priv->locales, info->id, info);

  info->layout_rows_by_id = g_hash_table_new_full (g_str_hash, g_str_equal,
                                                   NULL, g_object_unref);
  info->engine_rows_by_id = g_hash_table_new_full (g_str_hash, g_str_equal,
                                                   NULL, g_object_unref);

  list = gnome_xkb_info_get_all_layouts (priv->xkb_info);
  for (l = list; l; l = l->next)
    if (!g_hash_table_contains (layouts_with_locale, l->data))
      add_row_other (chooser, INPUT_SOURCE_TYPE_XKB, l->data);

  g_list_free (list);

  g_hash_table_destroy (layouts_with_locale);
}