Blame demos/scrapbook/scrapbook.c

Packit 4b6dd7
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
Packit 4b6dd7
/*
Packit 4b6dd7
 * GData Client
Packit 4b6dd7
 * Copyright (C) Joe Cortes 2010 <escozzia@gmail.com>
Packit 4b6dd7
 *
Packit 4b6dd7
 * GData Client is free software; you can redistribute it and/or
Packit 4b6dd7
 * modify it under the terms of the GNU Lesser General Public
Packit 4b6dd7
 * License as published by the Free Software Foundation; either
Packit 4b6dd7
 * version 2.1 of the License, or (at your option) any later version.
Packit 4b6dd7
 *
Packit 4b6dd7
 * GData Client is distributed in the hope that it will be useful,
Packit 4b6dd7
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 4b6dd7
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 4b6dd7
 * Lesser General Public License for more details.
Packit 4b6dd7
 *
Packit 4b6dd7
 * You should have received a copy of the GNU Lesser General Public
Packit 4b6dd7
 * License along with GData Client.  If not, see <http://www.gnu.org/licenses/>.
Packit 4b6dd7
 */
Packit 4b6dd7
Packit 4b6dd7
/*
Packit 4b6dd7
 * This is an extremely simple example program to query youtube videos
Packit 4b6dd7
 * and picasa pictures and add them to a grid.
Packit 4b6dd7
 * It was coded as part of the 2010 Google Code-In.
Packit 4b6dd7
 * Click on Properties to change the window's title, or authenticate
Packit 4b6dd7
 * yourself (it's assumed that your google and picasa ids are the same)
Packit 4b6dd7
 * It's also possible to upload files to picasa.
Packit 4b6dd7
 * Since this is only an example, intended to serve as documentation,
Packit 4b6dd7
 * it's probably full of bugs and a couple of awful programming practices.
Packit 4b6dd7
 * The program itself is of no practical use, but it does what it is
Packit 4b6dd7
 * meant to do and doesn't segfault randomly (I hope so :p).
Packit 4b6dd7
 */
Packit 4b6dd7
Packit 4b6dd7
#include "scrapbook.h"
Packit 4b6dd7
Packit 4b6dd7
static void
Packit 4b6dd7
open_in_web_browser (GtkWidget *widget, gchar *uri) /* quicky wrapper for gtk_show_uri */
Packit 4b6dd7
{
Packit 4b6dd7
	gtk_show_uri_on_window (GTK_WINDOW (gtk_widget_get_toplevel (widget)), uri, GDK_CURRENT_TIME, NULL);
Packit 4b6dd7
}
Packit 4b6dd7
Packit 4b6dd7
static void
Packit 4b6dd7
picture_selected (GtkTreeView *tree, GtkTreePath *path, GtkTreeViewColumn *column, ScrapPicSearch *self)
Packit 4b6dd7
{
Packit 4b6dd7
	GtkTreeModel 	*model;
Packit 4b6dd7
	GtkTreeIter		iter;
Packit 4b6dd7
	GDataEntry		*pic;
Packit 4b6dd7
	GdkPixbuf		*thumbnail;
Packit 4b6dd7
	GtkWidget		*button;
Packit 4b6dd7
	GtkWidget		*image;
Packit 4b6dd7
Packit 4b6dd7
	pic = g_slice_new				(GDataEntry);
Packit 4b6dd7
	model = gtk_tree_view_get_model	(tree);
Packit 4b6dd7
	gtk_tree_model_get_iter			(model, &iter, path);
Packit 4b6dd7
	gtk_tree_model_get				(model, &iter, COL_PIXBUF, &(thumbnail), P_COL_PIC, &(pic), -1);
Packit 4b6dd7
	gtk_widget_destroy				(self->search_data->window);
Packit 4b6dd7
	gtk_list_store_append (self->main_data->lStore, &iter);
Packit 4b6dd7
	gtk_list_store_set (self->main_data->lStore, &iter,
Packit 4b6dd7
									 ORIG_COL_PIXBUF, 	thumbnail,
Packit 4b6dd7
									 ORIG_COL_TITLE,	gdata_entry_get_title (pic),
Packit 4b6dd7
									 ORIG_COL_ENTRY, 	pic, -1);
Packit 4b6dd7
	if (self->main_data->currentRow[self->main_data->currentCol] > self->main_data->max_rows) {
Packit 4b6dd7
		self->main_data->currentCol++;
Packit 4b6dd7
		self->main_data->currentRow[self->main_data->currentCol] = 0;
Packit 4b6dd7
	}
Packit 4b6dd7
	image 	= gtk_image_new_from_pixbuf (thumbnail);
Packit 4b6dd7
	button	= gtk_button_new			();
Packit 4b6dd7
	self->file	= GDATA_PICASAWEB_FILE  (pic);
Packit 4b6dd7
	gtk_widget_show 					(image);
Packit 4b6dd7
	gtk_container_add 					(GTK_CONTAINER (button), image);
Packit 4b6dd7
	/*g_signal_connect 					(button, "clicked", G_CALLBACK (open_in_web_browser), gdata_entry_get_id (pic));
Packit 4b6dd7
	 * commented out, I can't seem to find anything that will give me a picture's URI */
Packit 4b6dd7
Packit 4b6dd7
	gtk_grid_attach (GTK_GRID (self->main_data->grid), button,
Packit 4b6dd7
	                 self->main_data->currentCol,
Packit 4b6dd7
	                 self->main_data->currentRow[self->main_data->currentCol],
Packit 4b6dd7
	                 1, 1);
Packit 4b6dd7
Packit 4b6dd7
	gtk_widget_show (button);
Packit 4b6dd7
	self->main_data->currentRow[self->main_data->currentCol]++;
Packit 4b6dd7
}
Packit 4b6dd7
Packit 4b6dd7
Packit 4b6dd7
Packit 4b6dd7
static void
Packit 4b6dd7
video_selected (GtkTreeView *tree, GtkTreePath *path, GtkTreeViewColumn *column, ScrapYTSearch *self)
Packit 4b6dd7
{
Packit 4b6dd7
	GtkTreeModel *model;
Packit 4b6dd7
	GtkTreeIter  iter;
Packit 4b6dd7
	GDataEntry   *video;
Packit 4b6dd7
	GdkPixbuf	 *thumbnail;
Packit 4b6dd7
	GtkWidget	 *button;
Packit 4b6dd7
	GtkWidget	 *image;
Packit 4b6dd7
	video = g_slice_new 			(GDataEntry);
Packit 4b6dd7
	model = gtk_tree_view_get_model (tree);
Packit 4b6dd7
	gtk_tree_model_get_iter 		(model, &iter, path);
Packit 4b6dd7
	gtk_tree_model_get 				(model, &iter, COL_PIXBUF, &(thumbnail), COL_VIDEO, &(video), -1);
Packit 4b6dd7
	gtk_widget_destroy 				(self->window);
Packit 4b6dd7
	gtk_list_store_append (self->main_data->lStore, &iter);
Packit 4b6dd7
	gtk_list_store_set (self->main_data->lStore, &iter,
Packit 4b6dd7
									 ORIG_COL_PIXBUF, thumbnail,
Packit 4b6dd7
									 ORIG_COL_TITLE, gdata_entry_get_title (video),
Packit 4b6dd7
									 ORIG_COL_ENTRY, video, -1);
Packit 4b6dd7
	if (self->main_data->currentRow[self->main_data->currentCol] > self->main_data->max_rows) {
Packit 4b6dd7
		self->main_data->currentCol++;
Packit 4b6dd7
		self->main_data->currentRow[self->main_data->currentCol] = 0;
Packit 4b6dd7
	}
Packit 4b6dd7
	image 	= gtk_image_new_from_pixbuf (thumbnail);
Packit 4b6dd7
	button 	= gtk_button_new ();
Packit 4b6dd7
	gtk_widget_show 	(image);
Packit 4b6dd7
	gtk_container_add 	(GTK_CONTAINER (button), image);
Packit 4b6dd7
	g_signal_connect (button, "clicked", G_CALLBACK (open_in_web_browser),
Packit 4b6dd7
	                  (gpointer) gdata_youtube_video_get_player_uri (GDATA_YOUTUBE_VIDEO (video)));
Packit 4b6dd7
Packit 4b6dd7
	gtk_grid_attach (GTK_GRID (self->main_data->grid), button,
Packit 4b6dd7
	                 self->main_data->currentCol,
Packit 4b6dd7
	                 self->main_data->currentRow[self->main_data->currentCol],
Packit 4b6dd7
	                 1, 1);
Packit 4b6dd7
Packit 4b6dd7
	gtk_widget_show (button);
Packit 4b6dd7
	self->main_data->currentRow[self->main_data->currentCol]++;
Packit 4b6dd7
}
Packit 4b6dd7
Packit 4b6dd7
static void
Packit 4b6dd7
p_display_tree (ScrapPicSearch *self)
Packit 4b6dd7
{
Packit 4b6dd7
	GtkCellRenderer 	*renderer;
Packit 4b6dd7
	GtkWidget			*scrollWin;
Packit 4b6dd7
	scrollWin = gtk_scrolled_window_new 		(NULL, NULL);
Packit 4b6dd7
	gtk_scrolled_window_set_policy 				(GTK_SCROLLED_WINDOW(scrollWin), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
Packit 4b6dd7
Packit 4b6dd7
	renderer = gtk_cell_renderer_pixbuf_new 	();
Packit 4b6dd7
	gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (self->tView), -1,
Packit 4b6dd7
												 "", renderer, "pixbuf",
Packit 4b6dd7
												 P_COL_PIXBUF, NULL);
Packit 4b6dd7
Packit 4b6dd7
	renderer = gtk_cell_renderer_text_new		();
Packit 4b6dd7
	gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (self->tView), -1,
Packit 4b6dd7
												 "", renderer, "text",
Packit 4b6dd7
												 P_COL_USER, NULL);
Packit 4b6dd7
Packit 4b6dd7
	renderer = gtk_cell_renderer_text_new		();
Packit 4b6dd7
	gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (self->tView), -1,
Packit 4b6dd7
												 "", renderer, "text",
Packit 4b6dd7
												 P_COL_TITLE, NULL);
Packit 4b6dd7
Packit 4b6dd7
	gtk_tree_view_set_model						(GTK_TREE_VIEW (self->tView), GTK_TREE_MODEL (self->lStore));
Packit 4b6dd7
	gtk_container_add 							(GTK_CONTAINER (scrollWin), self->tView);
Packit 4b6dd7
Packit 4b6dd7
	g_signal_connect							(self->tView, "row-activated", G_CALLBACK (picture_selected), self);
Packit 4b6dd7
Packit 4b6dd7
	gtk_widget_show 							(self->tView);
Packit 4b6dd7
	gtk_widget_show								(scrollWin);
Packit 4b6dd7
	gtk_box_pack_start							(GTK_BOX(self->search_data->box1), scrollWin, TRUE, TRUE, 2);
Packit 4b6dd7
}
Packit 4b6dd7
Packit 4b6dd7
Packit 4b6dd7
static void
Packit 4b6dd7
yt_display_tree (ScrapYTSearch *self)
Packit 4b6dd7
{
Packit 4b6dd7
	GtkCellRenderer 	*renderer;
Packit 4b6dd7
	GtkWidget			*scrollWin;
Packit 4b6dd7
	scrollWin = gtk_scrolled_window_new 		(NULL, NULL);
Packit 4b6dd7
	gtk_scrolled_window_set_policy 				(GTK_SCROLLED_WINDOW(scrollWin), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
Packit 4b6dd7
	renderer = gtk_cell_renderer_pixbuf_new 	();
Packit 4b6dd7
	gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (self->tView), -1,
Packit 4b6dd7
												 "", renderer, "pixbuf",
Packit 4b6dd7
												 COL_PIXBUF, NULL);
Packit 4b6dd7
	renderer = gtk_cell_renderer_text_new		();
Packit 4b6dd7
	gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (self->tView), -1,
Packit 4b6dd7
												 "", renderer, "text",
Packit 4b6dd7
												 COL_TITLE, NULL);
Packit 4b6dd7
	gtk_tree_view_set_model						(GTK_TREE_VIEW (self->tView), GTK_TREE_MODEL (self->lStore));
Packit 4b6dd7
	gtk_container_add 							(GTK_CONTAINER (scrollWin), self->tView);
Packit 4b6dd7
	g_signal_connect							(self->tView, "row-activated", G_CALLBACK (video_selected), self);
Packit 4b6dd7
	gtk_widget_show 							(self->tView);
Packit 4b6dd7
	gtk_widget_show								(scrollWin);
Packit 4b6dd7
	gtk_box_pack_start							(GTK_BOX(self->box1), scrollWin, TRUE, TRUE, 2);
Packit 4b6dd7
}
Packit 4b6dd7
Packit 4b6dd7
GDataMediaThumbnail *
Packit 4b6dd7
choose_best_thumbnail (GList *thumbnails, gint ideal_size)
Packit 4b6dd7
{
Packit 4b6dd7
	gint delta = G_MININT;
Packit 4b6dd7
	GDataMediaThumbnail *thumbnail = NULL;
Packit 4b6dd7
	for (; thumbnails != NULL; thumbnails = thumbnails->next) {
Packit 4b6dd7
		gint new_delta;
Packit 4b6dd7
		GDataMediaThumbnail *current = (GDataMediaThumbnail *) thumbnails->data;
Packit 4b6dd7
		new_delta = gdata_media_thumbnail_get_width (current) - ideal_size;
Packit 4b6dd7
		if (delta == 0) {
Packit 4b6dd7
			break;
Packit 4b6dd7
		} else if ((delta == G_MININT)
Packit 4b6dd7
		|| (delta < 0 && new_delta > delta)
Packit 4b6dd7
		|| (delta > 0 && new_delta < delta)) {
Packit 4b6dd7
			delta = new_delta;
Packit 4b6dd7
			thumbnail = current;
Packit 4b6dd7
		}
Packit 4b6dd7
	}
Packit 4b6dd7
	return thumbnail;
Packit 4b6dd7
}
Packit 4b6dd7
Packit 4b6dd7
static void
Packit 4b6dd7
find_pictures  (GDataEntry *entry, guint entry_key, guint entry_count, ScrapPicSearch *self)
Packit 4b6dd7
{
Packit 4b6dd7
	GtkTreeIter iter;
Packit 4b6dd7
	GList 				*thumbnails;
Packit 4b6dd7
	GDataMediaThumbnail	*thumbnail;
Packit 4b6dd7
	GFileInputStream	*input_stream;
Packit 4b6dd7
Packit 4b6dd7
	gtk_list_store_append (self->lStore, &iter);
Packit 4b6dd7
	gtk_list_store_set (self->lStore, &iter,
Packit 4b6dd7
							 P_COL_PIXBUF, NULL,
Packit 4b6dd7
							 P_COL_TITLE,  self->title,
Packit 4b6dd7
							 P_COL_USER,   self->user,
Packit 4b6dd7
							 P_COL_PIC,	   entry, -1);
Packit 4b6dd7
	thumbnails		= gdata_picasaweb_file_get_thumbnails (GDATA_PICASAWEB_FILE (entry));
Packit 4b6dd7
	thumbnail		= choose_best_thumbnail (thumbnails, THUMBNAIL_WIDTH);
Packit 4b6dd7
	if (thumbnail != NULL) {
Packit 4b6dd7
		GFile *thumbnail_file;
Packit 4b6dd7
		thumbnail_file 	= g_file_new_for_uri 					(gdata_media_thumbnail_get_uri (thumbnail));
Packit 4b6dd7
		input_stream   	= g_file_read							(thumbnail_file, NULL, NULL);
Packit 4b6dd7
		self->thumbnail	= gdk_pixbuf_new_from_stream_at_scale 	(G_INPUT_STREAM (input_stream), THUMBNAIL_WIDTH, -1,
Packit 4b6dd7
																 TRUE, NULL, NULL);
Packit 4b6dd7
		gtk_list_store_set (self->lStore, &iter, P_COL_PIXBUF, self->thumbnail, -1); /* we can now set the thumbnail ;) */
Packit 4b6dd7
		g_object_unref		(thumbnail_file);
Packit 4b6dd7
	}
Packit 4b6dd7
	gdata_query_set_q (self->query, NULL);
Packit 4b6dd7
}
Packit 4b6dd7
Packit 4b6dd7
Packit 4b6dd7
static void
Packit 4b6dd7
p_query_element (GDataEntry *entry, guint entry_key, guint entry_count, ScrapPSearch *self)
Packit 4b6dd7
{
Packit 4b6dd7
	GError				*error=NULL;
Packit 4b6dd7
	ScrapPicSearch		*picture;
Packit 4b6dd7
	GDataFeed *feed;
Packit 4b6dd7
Packit 4b6dd7
	picture = self->pic;
Packit 4b6dd7
	picture->title				= gdata_entry_get_title	(entry);
Packit 4b6dd7
	picture->query 				= picture->search_data->query;
Packit 4b6dd7
	picture->user				= self->user;
Packit 4b6dd7
	gdata_query_set_q 					(picture->query, picture->title);
Packit 4b6dd7
	feed = gdata_picasaweb_service_query_files (self->main_data->picasaweb_service, GDATA_PICASAWEB_ALBUM (entry), picture->query, NULL,
Packit 4b6dd7
	                                            (GDataQueryProgressCallback) find_pictures, picture, &error);
Packit 4b6dd7
Packit 4b6dd7
	if (error != NULL) {
Packit 4b6dd7
		g_print ("whoops, somebody raised an error!\n%s", error->message);
Packit 4b6dd7
		g_error_free (error);
Packit 4b6dd7
	}
Packit 4b6dd7
Packit 4b6dd7
	if (feed != NULL) {
Packit 4b6dd7
		g_object_unref (feed);
Packit 4b6dd7
	}
Packit 4b6dd7
}
Packit 4b6dd7
Packit 4b6dd7
static void
Packit 4b6dd7
p_text_callback (GtkWidget *widget, ScrapPSearch *self)
Packit 4b6dd7
{
Packit 4b6dd7
	GError *error 	= NULL;
Packit 4b6dd7
	GDataFeed *feed;
Packit 4b6dd7
Packit 4b6dd7
	self->user		= gtk_entry_get_text 			(GTK_ENTRY (self->user_entry));
Packit 4b6dd7
	self->pic->tView	= gtk_tree_view_new ();
Packit 4b6dd7
	feed = gdata_picasaweb_service_query_all_albums (self->main_data->picasaweb_service, self->query, self->user, NULL,
Packit 4b6dd7
	                                                 (GDataQueryProgressCallback) p_query_element, self, &error);
Packit 4b6dd7
	if (error != NULL) {
Packit 4b6dd7
		g_print ("someone raised an error\n%s\n",error->message);
Packit 4b6dd7
		g_error_free (error);
Packit 4b6dd7
	}
Packit 4b6dd7
Packit 4b6dd7
	if (feed != NULL) {
Packit 4b6dd7
		g_object_unref (feed);
Packit 4b6dd7
	}
Packit 4b6dd7
Packit 4b6dd7
	p_display_tree (self->pic);
Packit 4b6dd7
}
Packit 4b6dd7
Packit 4b6dd7
Packit 4b6dd7
/* ran as a callback for each individual element queried
Packit 4b6dd7
 * it takes the video found, a unique entry_key and entry_count and the data structure as arguments
Packit 4b6dd7
 * parts of this function were inspired (or simply taken) from the totem youtube plugin */
Packit 4b6dd7
static void
Packit 4b6dd7
yt_query_element (GDataEntry *entry, guint entry_key, guint entry_count, ScrapYTSearch *self)
Packit 4b6dd7
{
Packit 4b6dd7
	GtkTreeIter iter;
Packit 4b6dd7
	GList 				*thumbnails;
Packit 4b6dd7
	GDataMediaThumbnail *thumbnail;
Packit 4b6dd7
	const gchar *title; /* the video's title */
Packit 4b6dd7
	const gchar *uri; /* the video's URI */
Packit 4b6dd7
	GFileInputStream	*input_stream; /* this will be used to make a pixbuf to store the thumbnail */
Packit 4b6dd7
Packit 4b6dd7
	title	= gdata_entry_get_title 				(entry); /* self-explanatory, I hope */
Packit 4b6dd7
	uri		= gdata_youtube_video_get_player_uri	(GDATA_YOUTUBE_VIDEO (entry)); /* ditto */
Packit 4b6dd7
	g_print ("%s %s", title, uri);
Packit 4b6dd7
	gtk_list_store_append (self->lStore, &iter); /* make a new entry for this vid */
Packit 4b6dd7
	gtk_list_store_set (self->lStore, &iter,
Packit 4b6dd7
						   COL_PIXBUF, NULL, /* this will be set in a few moments */
Packit 4b6dd7
						   COL_TITLE, title,
Packit 4b6dd7
						   COL_VIDEO, entry,
Packit 4b6dd7
						   -1);
Packit 4b6dd7
	/* get a GList of thumbnails for the vid */
Packit 4b6dd7
	thumbnails = gdata_youtube_video_get_thumbnails (GDATA_YOUTUBE_VIDEO (entry));
Packit 4b6dd7
	thumbnail  = choose_best_thumbnail (thumbnails, THUMBNAIL_WIDTH);
Packit 4b6dd7
	if (thumbnail != NULL) {
Packit 4b6dd7
		GFile *thumbnail_file;
Packit 4b6dd7
		thumbnail_file 	= g_file_new_for_uri 					(gdata_media_thumbnail_get_uri (thumbnail));
Packit 4b6dd7
		input_stream   	= g_file_read							(thumbnail_file, NULL, NULL);
Packit 4b6dd7
		self->thumbnail	= gdk_pixbuf_new_from_stream_at_scale 	(G_INPUT_STREAM (input_stream), THUMBNAIL_WIDTH, -1,
Packit 4b6dd7
																 TRUE, NULL, NULL);
Packit 4b6dd7
		gtk_list_store_set (self->lStore, &iter, COL_PIXBUF, self->thumbnail, -1); /* we can now set the thumbnail ;) */
Packit 4b6dd7
		g_object_unref		(thumbnail_file);
Packit 4b6dd7
	}
Packit 4b6dd7
}
Packit 4b6dd7
Packit 4b6dd7
Packit 4b6dd7
static void
Packit 4b6dd7
yt_text_callback (GtkWidget *widget, ScrapYTSearch *self)
Packit 4b6dd7
{
Packit 4b6dd7
	GDataFeed *feed;
Packit 4b6dd7
Packit 4b6dd7
	self->txt = gtk_entry_get_text (GTK_ENTRY (self->txt_entry));
Packit 4b6dd7
	gdata_query_set_q	 				(self->query, self->txt);	/* set the string we'll be searching for in youtube */
Packit 4b6dd7
Packit 4b6dd7
	/* do the actual query, running yt_query_element for each object found */
Packit 4b6dd7
	feed = gdata_youtube_service_query_videos (self->main_data->youtube_service, self->query, NULL, (GDataQueryProgressCallback) yt_query_element,
Packit 4b6dd7
	                                           self, NULL);
Packit 4b6dd7
	if (feed != NULL) {
Packit 4b6dd7
		g_object_unref (feed);
Packit 4b6dd7
	}
Packit 4b6dd7
Packit 4b6dd7
	yt_display_tree (self); /* run yt_display_tree to show the results */
Packit 4b6dd7
}
Packit 4b6dd7
Packit 4b6dd7
Packit 4b6dd7
static void
Packit 4b6dd7
start_new_picasa_search (GtkWidget *widget, ScrapData *first)
Packit 4b6dd7
{
Packit 4b6dd7
	ScrapPSearch 				*self;
Packit 4b6dd7
	ScrapPicSearch				*picture;
Packit 4b6dd7
	GtkWidget *button, *box2;
Packit 4b6dd7
Packit 4b6dd7
	self = first->p_search;
Packit 4b6dd7
	picture 					= first->pic_search;
Packit 4b6dd7
	picture->search_data 		= self;
Packit 4b6dd7
	picture->search_data->pic	= picture;
Packit 4b6dd7
	picture->main_data			= self->main_data;
Packit 4b6dd7
	g_assert (GDATA_IS_PICASAWEB_SERVICE (first->picasaweb_service));
Packit 4b6dd7
	gtk_list_store_clear (self->pic->lStore);
Packit 4b6dd7
Packit 4b6dd7
	self->window = gtk_window_new 	(GTK_WINDOW_TOPLEVEL);
Packit 4b6dd7
	gtk_window_resize				(GTK_WINDOW (self->window), 400, 400);
Packit 4b6dd7
	g_signal_connect 				(self->window, "destroy", G_CALLBACK (gtk_widget_destroy), NULL);
Packit 4b6dd7
	g_signal_connect_swapped 		(self->window, "delete-event", G_CALLBACK (gtk_widget_destroy), NULL);
Packit 4b6dd7
Packit 4b6dd7
	/* our two boxes */
Packit 4b6dd7
Packit 4b6dd7
	self->box1 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 10); /* this box contains everything in our window */
Packit 4b6dd7
	gtk_container_add 				(GTK_CONTAINER (self->window), self->box1);
Packit 4b6dd7
	box2 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2);
Packit 4b6dd7
Packit 4b6dd7
	/* search bar */
Packit 4b6dd7
Packit 4b6dd7
	self->user_entry = gtk_entry_new ();
Packit 4b6dd7
	gtk_entry_set_text 				(GTK_ENTRY (self->user_entry), "User to search for");
Packit 4b6dd7
	g_signal_connect (self->user_entry, "activate", (GCallback) p_text_callback, self);
Packit 4b6dd7
	gtk_box_pack_start (GTK_BOX(box2), self->user_entry, TRUE, TRUE, 0);
Packit 4b6dd7
	gtk_widget_show    				(self->user_entry);
Packit 4b6dd7
Packit 4b6dd7
	/* Search button */
Packit 4b6dd7
	button = gtk_button_new_with_mnemonic ("_Search");
Packit 4b6dd7
	g_signal_connect (button, "clicked", (GCallback) p_text_callback, self);
Packit 4b6dd7
	gtk_box_pack_start (GTK_BOX (box2), button, FALSE, FALSE, 0);
Packit 4b6dd7
	gtk_widget_show (button);
Packit 4b6dd7
Packit 4b6dd7
	gtk_box_pack_end (GTK_BOX (self->box1), box2, FALSE, FALSE, 0); /* pack the box with the button and search bar */
Packit 4b6dd7
	gtk_widget_show (box2);
Packit 4b6dd7
Packit 4b6dd7
	gtk_widget_show (self->box1);
Packit 4b6dd7
	gtk_widget_show (self->window);
Packit 4b6dd7
}
Packit 4b6dd7
Packit 4b6dd7
Packit 4b6dd7
Packit 4b6dd7
static void
Packit 4b6dd7
start_new_youtube_search (GtkWidget *widget, ScrapData *first) /* *first is a pointer we use to talk to the main window */
Packit 4b6dd7
{
Packit 4b6dd7
	ScrapYTSearch *self; /* this struct will be used for all the data in the search, if there's time I'll make it into a GObject */
Packit 4b6dd7
	GtkWidget *button, *box2;
Packit 4b6dd7
Packit 4b6dd7
	self = first->yt_search;
Packit 4b6dd7
Packit 4b6dd7
	gtk_list_store_clear 				(self->lStore); /* clear it out */
Packit 4b6dd7
	self->tView  = gtk_tree_view_new 	();
Packit 4b6dd7
	/* window stuff */
Packit 4b6dd7
	self->window = gtk_window_new	(GTK_WINDOW_TOPLEVEL);
Packit 4b6dd7
	gtk_window_resize				(GTK_WINDOW (self->window), 400, 400);
Packit 4b6dd7
	g_signal_connect 				(self->window, "destroy", G_CALLBACK (gtk_widget_destroy), NULL);
Packit 4b6dd7
	g_signal_connect_swapped 		(self->window, "delete-event", G_CALLBACK (gtk_widget_destroy), NULL);
Packit 4b6dd7
Packit 4b6dd7
	/* our two boxes */
Packit 4b6dd7
Packit 4b6dd7
	self->box1 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 10); /* this box contains everything in our window */
Packit 4b6dd7
	gtk_container_add 				(GTK_CONTAINER (self->window), self->box1);
Packit 4b6dd7
	box2 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2);
Packit 4b6dd7
Packit 4b6dd7
	/* search bar */
Packit 4b6dd7
Packit 4b6dd7
	self->txt_entry = gtk_entry_new ();
Packit 4b6dd7
	g_signal_connect 				(self->txt_entry, "activate", G_CALLBACK (yt_text_callback), self);
Packit 4b6dd7
	gtk_box_pack_start (GTK_BOX (box2), self->txt_entry, TRUE, TRUE, 0);
Packit 4b6dd7
	gtk_widget_show    				(self->txt_entry);
Packit 4b6dd7
Packit 4b6dd7
	/* Search button */
Packit 4b6dd7
	button = gtk_button_new_with_mnemonic ("_Search");
Packit 4b6dd7
	g_signal_connect (button, "clicked", (GCallback) yt_text_callback, self);
Packit 4b6dd7
	gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
Packit 4b6dd7
	gtk_widget_show (button);
Packit 4b6dd7
Packit 4b6dd7
	gtk_box_pack_end (GTK_BOX (self->box1), box2, FALSE, FALSE, 0); /* pack the box with the button and search bar */
Packit 4b6dd7
Packit 4b6dd7
	gtk_widget_show (box2);
Packit 4b6dd7
	gtk_widget_show (self->box1);
Packit 4b6dd7
	gtk_widget_show (self->window);
Packit 4b6dd7
Packit 4b6dd7
Packit 4b6dd7
	/* everything else is implemented somewhere else */
Packit 4b6dd7
}
Packit 4b6dd7
Packit 4b6dd7
Packit 4b6dd7
static void
Packit 4b6dd7
properties_set (GtkWidget *widget, ScrapProps *self)
Packit 4b6dd7
{
Packit 4b6dd7
	GDataClientLoginAuthorizer *authorizer;
Packit 4b6dd7
	GList *domains = NULL; /* list of GDataAuthorizationDomains */
Packit 4b6dd7
	GError *error = NULL;
Packit 4b6dd7
Packit 4b6dd7
	/* Get the username and password to use */
Packit 4b6dd7
	self->main_data->username = g_strdup (gtk_entry_get_text (GTK_ENTRY (self->username_entry)));
Packit 4b6dd7
	self->main_data->password = g_strdup (gtk_entry_get_text (GTK_ENTRY (self->password_entry)));
Packit 4b6dd7
Packit 4b6dd7
	/* Domains we need to be authorised for */
Packit 4b6dd7
	domains = g_list_prepend (domains, gdata_youtube_service_get_primary_authorization_domain ());
Packit 4b6dd7
	domains = g_list_prepend (domains, gdata_picasaweb_service_get_primary_authorization_domain ());
Packit 4b6dd7
Packit 4b6dd7
	/* Authenticate */
Packit 4b6dd7
	authorizer = gdata_client_login_authorizer_new_for_authorization_domains (CLIENT_ID, domains);
Packit 4b6dd7
Packit 4b6dd7
	gdata_client_login_authorizer_authenticate (authorizer, self->main_data->username, self->main_data->password, NULL, &error);
Packit 4b6dd7
Packit 4b6dd7
	if (error != NULL) { /* we show this to the user in case they mistyped their password */
Packit 4b6dd7
		GtkWidget *label;
Packit 4b6dd7
Packit 4b6dd7
		label = gtk_label_new (error->message);
Packit 4b6dd7
		gtk_widget_show (label);
Packit 4b6dd7
		gtk_box_pack_end (GTK_BOX (self->box1), label, FALSE, FALSE, 0);
Packit 4b6dd7
Packit 4b6dd7
		g_print ("error\n%s\n", error->message);
Packit 4b6dd7
Packit 4b6dd7
		g_error_free (error);
Packit 4b6dd7
	}
Packit 4b6dd7
Packit 4b6dd7
	gdata_service_set_authorizer (GDATA_SERVICE (self->main_data->youtube_service), GDATA_AUTHORIZER (authorizer));
Packit 4b6dd7
	gdata_service_set_authorizer (GDATA_SERVICE (self->main_data->picasaweb_service), GDATA_AUTHORIZER (authorizer));
Packit 4b6dd7
Packit 4b6dd7
	gtk_widget_destroy (self->window);
Packit 4b6dd7
	g_object_unref (authorizer);
Packit 4b6dd7
}
Packit 4b6dd7
Packit 4b6dd7
static void
Packit 4b6dd7
properties_show (GtkWidget *widget, ScrapData *first)
Packit 4b6dd7
{
Packit 4b6dd7
	ScrapProps	*self;
Packit 4b6dd7
	GtkWidget *label, *button, *box2;
Packit 4b6dd7
Packit 4b6dd7
	self			= g_slice_new (struct _ScrapProps);
Packit 4b6dd7
	self->main_data	= first;
Packit 4b6dd7
	self->window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
Packit 4b6dd7
	g_signal_connect (self->window, "destroy", G_CALLBACK (gtk_widget_destroy), NULL);
Packit 4b6dd7
	g_signal_connect (self->window, "delete-event", G_CALLBACK (gtk_widget_destroy), NULL);
Packit 4b6dd7
Packit 4b6dd7
	self->box1 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 3);
Packit 4b6dd7
Packit 4b6dd7
	/* Username/Password labels box */
Packit 4b6dd7
	box2 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10);
Packit 4b6dd7
Packit 4b6dd7
	label = gtk_label_new ("Username");
Packit 4b6dd7
	gtk_widget_show (label);
Packit 4b6dd7
	gtk_box_pack_start (GTK_BOX (box2), label, TRUE, TRUE, 0);
Packit 4b6dd7
Packit 4b6dd7
	label = gtk_label_new ("Password");
Packit 4b6dd7
	gtk_widget_show (label);
Packit 4b6dd7
	gtk_box_pack_start (GTK_BOX (box2), label, TRUE, TRUE, 0);
Packit 4b6dd7
Packit 4b6dd7
	gtk_widget_show (box2);
Packit 4b6dd7
	gtk_box_pack_start (GTK_BOX (self->box1), box2, FALSE, FALSE, 0);
Packit 4b6dd7
Packit 4b6dd7
	/* Username/Password entries box */
Packit 4b6dd7
	box2 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10);
Packit 4b6dd7
	self->username_entry = gtk_entry_new ();
Packit 4b6dd7
Packit 4b6dd7
	if (self->main_data->username != NULL)
Packit 4b6dd7
		gtk_entry_set_text (GTK_ENTRY(self->username_entry), self->main_data->username);
Packit 4b6dd7
Packit 4b6dd7
	gtk_widget_show	   (self->username_entry);
Packit 4b6dd7
	gtk_box_pack_start (GTK_BOX (box2), self->username_entry, TRUE, TRUE, 0);
Packit 4b6dd7
Packit 4b6dd7
	self->password_entry = gtk_entry_new ();
Packit 4b6dd7
	gtk_entry_set_visibility (GTK_ENTRY (self->password_entry), FALSE);
Packit 4b6dd7
Packit 4b6dd7
	if (self->main_data->password != NULL)
Packit 4b6dd7
		gtk_entry_set_text (GTK_ENTRY(self->password_entry), self->main_data->password);
Packit 4b6dd7
Packit 4b6dd7
	gtk_widget_show	   (self->password_entry);
Packit 4b6dd7
	gtk_box_pack_start (GTK_BOX (box2), self->password_entry, TRUE, TRUE, 0);
Packit 4b6dd7
Packit 4b6dd7
	gtk_box_pack_start (GTK_BOX (self->box1), box2, FALSE, FALSE, 0);
Packit 4b6dd7
	gtk_widget_show (box2);
Packit 4b6dd7
Packit 4b6dd7
	/* OK button */
Packit 4b6dd7
	button = gtk_button_new_with_label ("_OK");
Packit 4b6dd7
	g_signal_connect (button, "clicked", (GCallback) properties_set, self);
Packit 4b6dd7
	gtk_widget_show (button);
Packit 4b6dd7
	gtk_box_pack_start (GTK_BOX (self->box1), button, FALSE, FALSE, 0);
Packit 4b6dd7
Packit 4b6dd7
	gtk_widget_show		(self->box1);
Packit 4b6dd7
	gtk_container_add	(GTK_CONTAINER (self->window), self->box1);
Packit 4b6dd7
	gtk_widget_show		(self->window);
Packit 4b6dd7
}
Packit 4b6dd7
Packit 4b6dd7
static void
Packit 4b6dd7
select_file (ScrapPUpload *self, GtkFileChooser *file_chooser)
Packit 4b6dd7
{
Packit 4b6dd7
	GFile *file;
Packit 4b6dd7
	GError *error = NULL;
Packit 4b6dd7
	GFileInfo *file_info;
Packit 4b6dd7
	GDataUploadStream *upload_stream;
Packit 4b6dd7
	GFileInputStream *file_stream;
Packit 4b6dd7
Packit 4b6dd7
	file = gtk_file_chooser_get_file (file_chooser);
Packit 4b6dd7
Packit 4b6dd7
	file_info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME "," G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
Packit 4b6dd7
	                               G_FILE_QUERY_INFO_NONE, NULL, NULL);
Packit 4b6dd7
Packit 4b6dd7
	/* upload our file, using the service we've set up, and metadata
Packit 4b6dd7
	 * set up in upload ()
Packit 4b6dd7
	 * no album is specified, but that should be easy to add */
Packit 4b6dd7
	upload_stream = gdata_picasaweb_service_upload_file (self->main_data->picasaweb_service, NULL /* for now uploading to drop box */,
Packit 4b6dd7
	                                                     self->file, g_file_info_get_display_name (file_info),
Packit 4b6dd7
	                                                     g_file_info_get_content_type (file_info), NULL, &error);
Packit 4b6dd7
Packit 4b6dd7
	g_object_unref (file_info);
Packit 4b6dd7
	g_object_unref (self->file);
Packit 4b6dd7
	self->file = NULL;
Packit 4b6dd7
Packit 4b6dd7
	if (error != NULL) {
Packit 4b6dd7
		g_print ("Error: %s\n", error->message);
Packit 4b6dd7
		g_error_free (error);
Packit 4b6dd7
Packit 4b6dd7
		g_object_unref (file);
Packit 4b6dd7
Packit 4b6dd7
		return;
Packit 4b6dd7
	}
Packit 4b6dd7
Packit 4b6dd7
	file_stream = g_file_read (file, NULL, NULL);
Packit 4b6dd7
	g_object_unref (file);
Packit 4b6dd7
Packit 4b6dd7
	g_output_stream_splice (G_OUTPUT_STREAM (upload_stream), G_INPUT_STREAM (file_stream),
Packit 4b6dd7
	                        G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET, NULL, NULL);
Packit 4b6dd7
Packit 4b6dd7
	self->file = gdata_picasaweb_service_finish_file_upload (self->main_data->picasaweb_service, upload_stream, NULL);
Packit 4b6dd7
Packit 4b6dd7
	g_object_unref (file_stream);
Packit 4b6dd7
	g_object_unref (upload_stream);
Packit 4b6dd7
}
Packit 4b6dd7
Packit 4b6dd7
static void
Packit 4b6dd7
got_name (GtkWidget *widget, ScrapData *scrap_data)
Packit 4b6dd7
{
Packit 4b6dd7
	ScrapPUpload *self;
Packit 4b6dd7
	GtkWidget *file_dialog;
Packit 4b6dd7
Packit 4b6dd7
	self = scrap_data->p_upload;
Packit 4b6dd7
Packit 4b6dd7
	gdata_entry_set_title 	(GDATA_ENTRY (self->file),
Packit 4b6dd7
							 gtk_entry_get_text (GTK_ENTRY (self->name)));
Packit 4b6dd7
	gdata_entry_set_summary	(GDATA_ENTRY (self->file),
Packit 4b6dd7
							 gtk_entry_get_text (GTK_ENTRY (self->description)));
Packit 4b6dd7
	gtk_widget_destroy 	(self->dialog);
Packit 4b6dd7
Packit 4b6dd7
	file_dialog = gtk_file_chooser_dialog_new ("Upload Photo", GTK_WINDOW (scrap_data->window), GTK_FILE_CHOOSER_ACTION_SAVE,
Packit 4b6dd7
	                                           "_Cancel", GTK_RESPONSE_CANCEL,
Packit 4b6dd7
	                                           "_Open", GTK_RESPONSE_ACCEPT,
Packit 4b6dd7
	                                           NULL);
Packit 4b6dd7
Packit 4b6dd7
	if (gtk_dialog_run (GTK_DIALOG (file_dialog)) == GTK_RESPONSE_ACCEPT) {
Packit 4b6dd7
		select_file (self, GTK_FILE_CHOOSER (file_dialog));
Packit 4b6dd7
	}
Packit 4b6dd7
Packit 4b6dd7
	/* since the upload blocks, it's safe to assume the widget won't
Packit 4b6dd7
	 * be destroyed until we're done */
Packit 4b6dd7
	gtk_widget_destroy (file_dialog);
Packit 4b6dd7
}
Packit 4b6dd7
Packit 4b6dd7
static void
Packit 4b6dd7
upload (GtkWidget *widget, ScrapData *first)
Packit 4b6dd7
{
Packit 4b6dd7
	ScrapPUpload 	*self;
Packit 4b6dd7
	GtkWidget *label, *content_area;
Packit 4b6dd7
	label = gtk_label_new ("Enter photo name and description");
Packit 4b6dd7
	self = first->p_upload;
Packit 4b6dd7
Packit 4b6dd7
	/* we make a new file, without an id (it will be assigned automatically later on) */
Packit 4b6dd7
	self->file  = gdata_picasaweb_file_new (NULL);
Packit 4b6dd7
	/* dialog to get the file's name and description */
Packit 4b6dd7
	self->dialog = gtk_dialog_new();
Packit 4b6dd7
	content_area = gtk_dialog_get_content_area (GTK_DIALOG (self->dialog));
Packit 4b6dd7
Packit 4b6dd7
	gtk_widget_show (label);
Packit 4b6dd7
	gtk_box_pack_start (GTK_BOX (content_area), label, FALSE, FALSE, 0);
Packit 4b6dd7
Packit 4b6dd7
	self->name	= gtk_entry_new ();
Packit 4b6dd7
	g_signal_connect 	(self->name, "activate", G_CALLBACK (got_name), self);
Packit 4b6dd7
	gtk_widget_show  	(self->name);
Packit 4b6dd7
	gtk_box_pack_start (GTK_BOX (content_area), self->name, TRUE, TRUE, 0);
Packit 4b6dd7
Packit 4b6dd7
	self->description = gtk_entry_new ();
Packit 4b6dd7
	g_signal_connect 	(self->description, "activate", G_CALLBACK (got_name), first);
Packit 4b6dd7
	gtk_widget_show  	(self->description);
Packit 4b6dd7
	gtk_box_pack_start (GTK_BOX (content_area), self->description, TRUE, TRUE, 0);
Packit 4b6dd7
Packit 4b6dd7
	gtk_widget_show		(self->dialog);
Packit 4b6dd7
}
Packit 4b6dd7
Packit 4b6dd7
int
Packit 4b6dd7
main(int argc, char **argv)
Packit 4b6dd7
{
Packit 4b6dd7
	ScrapData 		*scrapbook;
Packit 4b6dd7
	ScrapPSearch 	*picasaSearch;
Packit 4b6dd7
	ScrapYTSearch	*youtubeSearch;
Packit 4b6dd7
	ScrapPicSearch	*photoSearch;
Packit 4b6dd7
	ScrapPUpload	*fUpload;
Packit 4b6dd7
	GtkWidget *button;
Packit 4b6dd7
	GtkWidget *vbox;
Packit 4b6dd7
Packit 4b6dd7
	scrapbook = g_slice_new (struct _ScrapData);
Packit 4b6dd7
	scrapbook->max_rows			= 5;
Packit 4b6dd7
Packit 4b6dd7
	gtk_init	(&argc, &argv);
Packit 4b6dd7
Packit 4b6dd7
	scrapbook->currentCol 							= 0;
Packit 4b6dd7
	scrapbook->currentRow[scrapbook->currentCol]	= 0;
Packit 4b6dd7
Packit 4b6dd7
	scrapbook->lStore   = gtk_list_store_new (ORIG_N_COLS, GDK_TYPE_PIXBUF, G_TYPE_STRING, GDATA_TYPE_ENTRY);
Packit 4b6dd7
	scrapbook->window 	= gtk_window_new 	(GTK_WINDOW_TOPLEVEL);
Packit 4b6dd7
	gtk_window_set_title (GTK_WINDOW (scrapbook->window), "Scrapbook");
Packit 4b6dd7
	g_signal_connect (scrapbook->window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
Packit 4b6dd7
	g_signal_connect (scrapbook->window, "delete-event", G_CALLBACK (gtk_main_quit), NULL);
Packit 4b6dd7
Packit 4b6dd7
	youtubeSearch 				= g_slice_new (struct _ScrapYTSearch); /* get some memory for the structure */
Packit 4b6dd7
	youtubeSearch->txt	 		= NULL;
Packit 4b6dd7
	scrapbook->yt_search 		= youtubeSearch;
Packit 4b6dd7
	youtubeSearch->main_data 	= scrapbook;
Packit 4b6dd7
	/* create a new query, without any search text, starting at 0, and search only MAX_RESULTS results */
Packit 4b6dd7
	youtubeSearch->query = gdata_query_new_with_limits (NULL, 0, MAX_RESULTS);
Packit 4b6dd7
	/* create a new youtube service, giving it our developer key; google no longer uses client ids so we send in an empty string (NULL gives an error) */
Packit 4b6dd7
	scrapbook->youtube_service = gdata_youtube_service_new (DEVELOPER_KEY, NULL);
Packit 4b6dd7
	/* create a new list store and tree to show the user the results
Packit 4b6dd7
	 * it has three columns (two of which are displayed): a pixbuf for the thumbnail, the title, and the video data itself (as a gdata generic entry) */
Packit 4b6dd7
	youtubeSearch->lStore = gtk_list_store_new 	(N_COLS, GDK_TYPE_PIXBUF, G_TYPE_STRING, GDATA_TYPE_ENTRY);
Packit 4b6dd7
Packit 4b6dd7
	picasaSearch 				= g_slice_new (struct _ScrapPSearch);
Packit 4b6dd7
	scrapbook->p_search 		= picasaSearch;
Packit 4b6dd7
	picasaSearch->main_data 	= scrapbook;
Packit 4b6dd7
	picasaSearch->query 		= gdata_query_new_with_limits (NULL, 0, MAX_RESULTS);
Packit 4b6dd7
	scrapbook->picasaweb_service = gdata_picasaweb_service_new (NULL);
Packit 4b6dd7
Packit 4b6dd7
	photoSearch					= g_slice_new (struct _ScrapPicSearch);
Packit 4b6dd7
	scrapbook->p_search->pic	= photoSearch;
Packit 4b6dd7
	scrapbook->pic_search		= photoSearch;
Packit 4b6dd7
	photoSearch->lStore = gtk_list_store_new (P_N_COLS, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING, GDATA_TYPE_ENTRY);
Packit 4b6dd7
Packit 4b6dd7
	fUpload						= g_slice_new (struct _ScrapPUpload);
Packit 4b6dd7
	scrapbook->p_upload			= fUpload;
Packit 4b6dd7
	fUpload->main_data			= scrapbook;
Packit 4b6dd7
Packit 4b6dd7
	scrapbook->box1 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
Packit 4b6dd7
	scrapbook->grid = gtk_grid_new ();
Packit 4b6dd7
Packit 4b6dd7
	vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);
Packit 4b6dd7
Packit 4b6dd7
	/* Add buttons to the main window */
Packit 4b6dd7
	button = gtk_button_new_with_mnemonic ("Add YouTube _Video");
Packit 4b6dd7
	g_signal_connect (button, "clicked", (GCallback) start_new_youtube_search, scrapbook);
Packit 4b6dd7
	gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
Packit 4b6dd7
	gtk_widget_show (button);
Packit 4b6dd7
Packit 4b6dd7
	button = gtk_button_new_with_mnemonic ("Add PicasaWeb _Photo");
Packit 4b6dd7
	g_signal_connect (button, "clicked", (GCallback) start_new_picasa_search, scrapbook);
Packit 4b6dd7
	gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
Packit 4b6dd7
	gtk_widget_show (button);
Packit 4b6dd7
Packit 4b6dd7
	button = gtk_button_new_with_mnemonic ("P_roperties");
Packit 4b6dd7
	g_signal_connect (button, "clicked", (GCallback) properties_show, scrapbook);
Packit 4b6dd7
	gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
Packit 4b6dd7
	gtk_widget_show (button);
Packit 4b6dd7
Packit 4b6dd7
	button = gtk_button_new_with_mnemonic ("_Upload Photo to PicasaWeb");
Packit 4b6dd7
	g_signal_connect (button, "clicked", (GCallback) upload, scrapbook);
Packit 4b6dd7
	gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
Packit 4b6dd7
	gtk_widget_show (button);
Packit 4b6dd7
Packit 4b6dd7
	gtk_widget_show (vbox);
Packit 4b6dd7
	gtk_box_pack_start (GTK_BOX (scrapbook->box1), vbox, FALSE, FALSE, 5);
Packit 4b6dd7
Packit 4b6dd7
	gtk_box_pack_start (GTK_BOX (scrapbook->box1), scrapbook->grid, TRUE, TRUE, 0);
Packit 4b6dd7
	gtk_widget_show (scrapbook->grid);
Packit 4b6dd7
	gtk_widget_show		(scrapbook->box1);
Packit 4b6dd7
	gtk_container_add	(GTK_CONTAINER (scrapbook->window), scrapbook->box1);
Packit 4b6dd7
	gtk_widget_show		(scrapbook->window);
Packit 4b6dd7
	gtk_main			();
Packit 4b6dd7
	return 0;
Packit 4b6dd7
}