/**
 * shell_app_system_get_app:
 *
 * Find or create a #ShellApp corresponding to an id; if already cached
 * elsewhere in memory, return that instance.  Otherwise, create a new
 * one.
 *
 * Return value: (transfer full): The #ShellApp for id, or %NULL if none
 */
ShellApp *
shell_app_system_get_app (ShellAppSystem   *self,
                          const char       *id)
{
  ShellAppInfo *info;
  ShellApp *app;

  app = g_hash_table_lookup (self->priv->app_id_to_app, id);
  if (app)
    return g_object_ref (app);

  info = g_hash_table_lookup (self->priv->app_id_to_info, id);
  if (!info)
    return NULL;

  app = _shell_app_new (info);

  return app;
}
Ejemplo n.º 2
0
static void
on_settings_tree_changed_cb (GMenuTree *tree,
                             gpointer   user_data)
{
  ShellAppSystem *self = SHELL_APP_SYSTEM (user_data);
  GError *error = NULL;
  GHashTable *new_settings;
  GHashTableIter iter;
  gpointer key, value;

  g_assert (tree == self->priv->settings_tree);

  g_hash_table_remove_all (self->priv->setting_id_to_app);
  if (!gmenu_tree_load_sync (self->priv->settings_tree, &error))
    {
      if (error)
        {
          g_warning ("Failed to load apps: %s", error->message);
          g_error_free (error);
        }
      else
        {
          g_warning ("Failed to load apps");
        }
      return;
    }

  new_settings = get_flattened_entries_from_tree (tree);

  g_hash_table_iter_init (&iter, new_settings);
  while (g_hash_table_iter_next (&iter, &key, &value))
    {
      const char *id = key;
      GMenuTreeEntry *entry = value;
      ShellApp *app;

      app = _shell_app_new (entry);
      g_hash_table_replace (self->priv->setting_id_to_app, (char*)id, app);
    }
  g_hash_table_destroy (new_settings);
}
Ejemplo n.º 3
0
/**
 * shell_app_system_lookup_app:
 *
 * Find a #ShellApp corresponding to an id.
 *
 * Return value: (transfer none): The #ShellApp for id, or %NULL if none
 */
ShellApp *
shell_app_system_lookup_app (ShellAppSystem   *self,
                             const char       *id)
{
  ShellAppSystemPrivate *priv = self->priv;
  ShellApp *app;
  GDesktopAppInfo *info;

  app = g_hash_table_lookup (priv->id_to_app, id);
  if (app)
    return app;

  info = g_desktop_app_info_new (id);
  if (!info)
    return NULL;

  app = _shell_app_new (info);
  g_hash_table_insert (priv->id_to_app, (char *) shell_app_get_id (app), app);
  g_object_unref (info);
  return app;
}
Ejemplo n.º 4
0
static void
on_apps_tree_changed_cb (GMenuTree *tree,
                         gpointer   user_data)
{
  ShellAppSystem *self = SHELL_APP_SYSTEM (user_data);
  GError *error = NULL;
  GHashTable *new_apps;
  GHashTableIter iter;
  gpointer key, value;
  GSList *removed_apps = NULL;
  GSList *removed_node;

  g_assert (tree == self->priv->apps_tree);

  g_hash_table_remove_all (self->priv->visible_id_to_app);
  g_slist_free_full (self->priv->known_vendor_prefixes, g_free);
  self->priv->known_vendor_prefixes = NULL;

  if (!gmenu_tree_load_sync (self->priv->apps_tree, &error))
    {
      if (error)
        {
          g_warning ("Failed to load apps: %s", error->message);
          g_error_free (error);
        }
      else
        {
          g_warning ("Failed to load apps");
        }
      return;
    }

  new_apps = get_flattened_entries_from_tree (self->priv->apps_tree);
  g_hash_table_iter_init (&iter, new_apps);
  while (g_hash_table_iter_next (&iter, &key, &value))
    {
      const char *id = key;
      GMenuTreeEntry *entry = value;
      GMenuTreeEntry *old_entry;
      char *prefix;
      ShellApp *app;
      
      prefix = get_prefix_for_entry (entry);
      
      if (prefix != NULL
          && !g_slist_find_custom (self->priv->known_vendor_prefixes, prefix,
                                   (GCompareFunc)g_strcmp0))
        self->priv->known_vendor_prefixes = g_slist_append (self->priv->known_vendor_prefixes,
                                                            prefix);
      else
        g_free (prefix);
      
      app = g_hash_table_lookup (self->priv->id_to_app, id);
      if (app != NULL)
        {
          /* We hold a reference to the original entry temporarily,
           * because otherwise the hash table would be referencing
           * potentially free'd memory until we replace it below with
           * the new data.
           */
          old_entry = shell_app_get_tree_entry (app);
          gmenu_tree_item_ref (old_entry);
          _shell_app_set_entry (app, entry);
          g_object_ref (app);  /* Extra ref, removed in _replace below */
        }
      else
        {
          old_entry = NULL;
          app = _shell_app_new (entry);
        }
      /* Note that "id" is owned by app->entry.  Since we're always
       * setting a new entry, even if the app already exists in the
       * hash table we need to replace the key so that the new id
       * string is pointed to.
       */
      g_hash_table_replace (self->priv->id_to_app, (char*)id, app);
      if (!gmenu_tree_entry_get_is_nodisplay_recurse (entry))
        g_hash_table_replace (self->priv->visible_id_to_app, (char*)id, app);

      if (old_entry)
        gmenu_tree_item_unref (old_entry);
    }
  /* Now iterate over the apps again; we need to unreference any apps
   * which have been removed.  The JS code may still be holding a
   * reference; that's fine.
   */
  g_hash_table_iter_init (&iter, self->priv->id_to_app);
  while (g_hash_table_iter_next (&iter, &key, &value))
    {
      const char *id = key;
      
      if (!g_hash_table_lookup (new_apps, id))
        removed_apps = g_slist_prepend (removed_apps, (char*)id);
    }
  for (removed_node = removed_apps; removed_node; removed_node = removed_node->next)
    {
      const char *id = removed_node->data;
      g_hash_table_remove (self->priv->id_to_app, id);
    }
  g_slist_free (removed_apps);
      
  g_hash_table_destroy (new_apps);

  g_signal_emit (self, signals[INSTALLED_CHANGED], 0);
}