static void
gs_shell_overview_get_popular_rotating_cb (GObject *source_object,
					   GAsyncResult *res,
					   gpointer user_data)
{
	LoadData *load_data = (LoadData *) user_data;
	GsShellOverview *self = load_data->self;
	GsShellOverviewPrivate *priv = gs_shell_overview_get_instance_private (self);
	GsPluginLoader *plugin_loader = GS_PLUGIN_LOADER (source_object);
	GList *l;
	GsApp *app;
	gint i;
	GtkWidget *tile;
	g_autoptr(GError) error = NULL;
	g_autoptr(GsAppList) list = NULL;

	/* get popular apps */
	list = gs_plugin_loader_get_category_apps_finish (plugin_loader, res, &error);
	if (list == NULL) {
		if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
			g_warning ("failed to get recommended applications: %s", error->message);
		gtk_widget_hide (priv->popular_rotating_heading);
		gtk_widget_hide (priv->box_popular_rotating);
		goto out;
	} else if (g_list_length (list) < N_TILES) {
		g_warning ("hiding recommended applications: found only %d to show, need at least %d", g_list_length (list), N_TILES);
		gtk_widget_hide (priv->popular_rotating_heading);
		gtk_widget_hide (priv->box_popular_rotating);
		goto out;
	}
	gs_plugin_list_randomize (&list);

	gtk_widget_show (priv->popular_rotating_heading);
	gtk_widget_show (priv->box_popular_rotating);

	gs_container_remove_all (GTK_CONTAINER (priv->box_popular_rotating));

	for (l = list, i = 0; l != NULL && i < N_TILES; l = l->next, i++) {
		app = GS_APP (l->data);
		tile = gs_popular_tile_new (app);
		g_signal_connect (tile, "clicked",
			  G_CALLBACK (popular_tile_clicked), self);
		gtk_container_add (GTK_CONTAINER (priv->box_popular_rotating), tile);
	}

	priv->empty = FALSE;

out:
	load_data_free (load_data);
	priv->loading_popular_rotating = FALSE;
	priv->refresh_count--;
	if (priv->refresh_count == 0) {
		priv->cache_valid = TRUE;
		g_signal_emit (self, signals[SIGNAL_REFRESHED], 0);
	}
}
static void
gs_plugin_loader_get_category_apps_finish_sync (GsPluginLoader *plugin_loader,
						GAsyncResult *res,
						GsPluginLoaderHelper *helper)
{
	helper->list = gs_plugin_loader_get_category_apps_finish (plugin_loader,
								  res,
								  helper->error);
	g_main_loop_quit (helper->loop);
}
/**
 * gs_shell_category_get_apps_cb:
 **/
static void
gs_shell_category_get_apps_cb (GObject *source_object,
			       GAsyncResult *res,
			       gpointer user_data)
{
	gint i = 0;
	GList *l;
	GList *list;
	GsApp *app;
	GtkWidget *tile;
	GsShellCategory *shell = GS_SHELL_CATEGORY (user_data);
	GsShellCategoryPrivate *priv = shell->priv;
	GsPluginLoader *plugin_loader = GS_PLUGIN_LOADER (source_object);
	_cleanup_error_free_ GError *error = NULL;

	list = gs_plugin_loader_get_category_apps_finish (plugin_loader,
							  res,
							  &error);
	if (list == NULL) {
		if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
			g_warning ("failed to get apps for category apps: %s", error->message);
		goto out;
	}
	gtk_grid_remove_column (GTK_GRID (priv->category_detail_grid), 1);
	gtk_grid_remove_column (GTK_GRID (priv->category_detail_grid), 0);

	for (l = list, i = 0; l != NULL; l = l->next, i++) {
		app = GS_APP (l->data);
		tile = gs_app_tile_new (app);
		g_signal_connect (tile, "clicked",
				  G_CALLBACK (app_tile_clicked), shell);
		gtk_grid_attach (GTK_GRID (priv->category_detail_grid), tile, (i % 2), i / 2, 1, 1);
	}

	if (i == 1)
		gtk_grid_attach (GTK_GRID (priv->category_detail_grid), priv->col1_placeholder, 1, 0, 1, 1);

out:
	gs_plugin_list_free (list);

}