[libgdata] demos: Add a “scrapbook” demo of PicasaWeb and YouTube services



commit f330d66a19e41f5af5ddd568e103fe9770271f51
Author: Joe C <escozzia gmail com>
Date:   Sun Jan 16 16:27:55 2011 +0000

    demos: Add a âscrapbookâ demo of PicasaWeb and YouTube services
    
    Helps: bgo#628069

 Makefile.am                 |   34 +++
 configure.ac                |    3 +
 demos/scrapbook/scrap.c     |  639 +++++++++++++++++++++++++++++++++++++++++++
 demos/scrapbook/scrapdata.h |  182 ++++++++++++
 4 files changed, 858 insertions(+), 0 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index 1653a84..ee9989f 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -527,6 +527,40 @@ gcov:
 	@echo "Need to reconfigure with --enable-gcov"
 endif
 
+# Demo programs
+noinst_PROGRAMS =
+
+if HAVE_GTK
+noinst_PROGRAMS += demos/scrapbook/scrapbook
+endif
+
+demos_scrapbook_scrapbook_SOURCES = \
+	demos/scrapbook/scrap.c \
+	demos/scrapbook/scrapdata.h \
+	$(NULL)
+
+demos_scrapbook_scrapbook_CPPFLAGS = \
+	-I$(top_srcdir)/ \
+	-I$(top_srcdir)/gdata \
+	-DG_LOG_DOMAIN=\"scrapbook\" \
+	$(DISABLE_DEPRECATED) \
+	$(AM_CPPFLAGS) \
+	$(NULL)
+
+demos_scrapbook_scrapbook_CFLAGS = \
+	$(WARN_CFLAGS) \
+	$(GTK_CFLAGS) \
+	$(GDATA_CFLAGS) \
+	$(AM_CFLAGS) \
+	$(NULL)
+
+demos_scrapbook_scrapbook_LDADD = \
+	$(top_builddir)/gdata/libgdata.la \
+	$(GTK_LIBS) \
+	$(GDATA_LIBS) \
+	$(AM_LDADD) \
+	$(NULL)
+
 # Cleaning
 EXTRA_DIST += \
 	autogen.sh		\
diff --git a/configure.ac b/configure.ac
index 4152803..e113872 100644
--- a/configure.ac
+++ b/configure.ac
@@ -74,6 +74,9 @@ fi
 AC_SUBST(GDK_PIXBUF_CFLAGS)
 AC_SUBST(GDK_PIXBUF_LIBS)
 
+PKG_CHECK_MODULES([GTK], [gtk+-3.0], [have_gtk=yes], [have_gtk=no])
+AM_CONDITIONAL([HAVE_GTK], [test "x$have_gtk" = "xyes"])
+
 # GNOME support, which pulls in libsoup-gnome-2.4 to provide transparent proxy support
 AC_MSG_CHECKING(whether to build with GNOME support)
 AC_ARG_ENABLE(gnome, AS_HELP_STRING([--enable-gnome], [Whether to enable GNOME support]),, enable_gnome=yes)
diff --git a/demos/scrapbook/scrap.c b/demos/scrapbook/scrap.c
new file mode 100644
index 0000000..4bcf833
--- /dev/null
+++ b/demos/scrapbook/scrap.c
@@ -0,0 +1,639 @@
+#include "scrapdata.h"
+
+
+static void
+open_in_web_browser (GtkWidget *widget, gchar *uri) /* quicky wrapper for gtk_show_uri */
+{
+	gtk_show_uri			(gtk_widget_get_screen (widget), uri, GDK_CURRENT_TIME, NULL);
+}
+
+static void
+picture_selected (GtkTreeView *tree, GtkTreePath *path, GtkTreeViewColumn *column, ScrapPicSearch *self)
+{
+	GtkTreeModel 	*model;
+	GtkTreeIter		iter;
+	GDataEntry		*pic;
+	GdkPixbuf		*thumbnail;
+	GtkWidget		*button;
+	GtkWidget		*image;
+	
+	pic = g_slice_new				(GDataEntry);
+	model = gtk_tree_view_get_model	(tree);
+	gtk_tree_model_get_iter			(model, &iter, path);
+	gtk_tree_model_get				(model, &iter, COL_PIXBUF, &(thumbnail), P_COL_PIC, &(pic), -1);
+	gtk_widget_destroy				(self->search_data->window);
+	gtk_list_store_append			(self->main_data->lStore, &(self->main_data->iter));
+	gtk_list_store_set				(self->main_data->lStore, &(self->main_data->iter),
+									 ORIG_COL_PIXBUF, 	thumbnail,
+									 ORIG_COL_TITLE,	gdata_entry_get_title (pic),
+									 ORIG_COL_ENTRY, 	pic, -1);
+	if (self->main_data->currentRow[self->main_data->currentCol] > self->main_data->max_rows) {
+		self->main_data->currentCol++;
+		self->main_data->currentRow[self->main_data->currentCol] = 0;
+	}
+	image 	= gtk_image_new_from_pixbuf (thumbnail);
+	button	= gtk_button_new			();
+	self->file	= GDATA_PICASAWEB_FILE  (pic);
+	gtk_widget_show 					(image);
+	gtk_container_add 					(GTK_CONTAINER (button), image);
+	/*g_signal_connect 					(button, "clicked", G_CALLBACK (open_in_web_browser), gdata_entry_get_id (pic));
+	 * commented out, I can't seem to find anything that will give me a picture's URI */
+	gtk_table_attach_defaults 			(GTK_TABLE(self->main_data->table), button,
+										 self->main_data->currentRow[self->main_data->currentCol],
+										 self->main_data->currentRow[self->main_data->currentCol]+1,
+										 self->main_data->currentCol, self->main_data->currentCol+1);
+	gtk_widget_show (button);
+	self->main_data->currentRow[self->main_data->currentCol]++;
+	g_object_unref (self->tView);
+}
+	
+
+
+static void
+video_selected (GtkTreeView *tree, GtkTreePath *path, GtkTreeViewColumn *column, ScrapYTSearch *self)
+{
+	GtkTreeModel *model;
+	GtkTreeIter  iter;
+	GDataEntry   *video;
+	GdkPixbuf	 *thumbnail;
+	GtkWidget	 *button;
+	GtkWidget	 *image;
+	video = g_slice_new 			(GDataEntry);
+	model = gtk_tree_view_get_model (tree);
+	gtk_tree_model_get_iter 		(model, &iter, path);
+	gtk_tree_model_get 				(model, &iter, COL_PIXBUF, &(thumbnail), COL_VIDEO, &(video), -1);
+	gtk_widget_destroy 				(self->window);
+	gtk_list_store_append			(self->main_data->lStore, &(self->main_data->iter));
+	gtk_list_store_set				(self->main_data->lStore, &(self->main_data->iter),
+									 ORIG_COL_PIXBUF, thumbnail,
+									 ORIG_COL_TITLE, gdata_entry_get_title (video),
+									 ORIG_COL_ENTRY, video, -1);
+	if (self->main_data->currentRow[self->main_data->currentCol] > self->main_data->max_rows) {
+		self->main_data->currentCol++;
+		self->main_data->currentRow[self->main_data->currentCol] = 0;
+	}
+	image 	= gtk_image_new_from_pixbuf (thumbnail);
+	button 	= gtk_button_new ();
+	gtk_widget_show 	(image);
+	gtk_container_add 	(GTK_CONTAINER (button), image);
+	g_signal_connect (button, "clicked", G_CALLBACK (open_in_web_browser), gdata_youtube_video_get_player_uri (GDATA_YOUTUBE_VIDEO (video)));
+	gtk_table_attach_defaults (GTK_TABLE(self->main_data->table), button,
+										 self->main_data->currentRow[self->main_data->currentCol],
+										 self->main_data->currentRow[self->main_data->currentCol]+1,
+										 self->main_data->currentCol, self->main_data->currentCol+1);
+	gtk_widget_show (button);
+	self->main_data->currentRow[self->main_data->currentCol]++;
+	g_object_unref (self->tView);
+}
+
+static void
+p_display_tree (ScrapPicSearch *self)
+{
+	GtkCellRenderer 	*renderer;
+	GtkWidget			*scrollWin;
+	scrollWin = gtk_scrolled_window_new 		(NULL, NULL);
+	gtk_scrolled_window_set_policy 				(GTK_SCROLLED_WINDOW(scrollWin), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
+	
+	renderer = gtk_cell_renderer_pixbuf_new 	();
+	gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (self->tView), -1,
+												 "", renderer, "pixbuf",
+												 P_COL_PIXBUF, NULL);
+												 
+	renderer = gtk_cell_renderer_text_new		();
+	gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (self->tView), -1,
+												 "", renderer, "text",
+												 P_COL_USER, NULL);
+	
+	renderer = gtk_cell_renderer_text_new		();
+	gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (self->tView), -1,
+												 "", renderer, "text",
+												 P_COL_TITLE, NULL);
+	
+	gtk_tree_view_set_model						(GTK_TREE_VIEW (self->tView), GTK_TREE_MODEL (self->lStore));
+	gtk_container_add 							(GTK_CONTAINER (scrollWin), self->tView);
+	
+	g_signal_connect							(self->tView, "row-activated", G_CALLBACK (picture_selected), self);
+	
+	gtk_widget_show 							(self->tView);
+	gtk_widget_show								(scrollWin);
+	gtk_box_pack_start							(GTK_BOX(self->search_data->box1), scrollWin, TRUE, TRUE, 2);
+}
+
+
+static void
+yt_display_tree (ScrapYTSearch *self)
+{
+	GtkCellRenderer 	*renderer;
+	GtkWidget			*scrollWin;
+	scrollWin = gtk_scrolled_window_new 		(NULL, NULL);
+	gtk_scrolled_window_set_policy 				(GTK_SCROLLED_WINDOW(scrollWin), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
+	renderer = gtk_cell_renderer_pixbuf_new 	();
+	gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (self->tView), -1,
+												 "", renderer, "pixbuf",
+												 COL_PIXBUF, NULL);
+	renderer = gtk_cell_renderer_text_new		();
+	gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (self->tView), -1,
+												 "", renderer, "text",
+												 COL_TITLE, NULL);
+	gtk_tree_view_set_model						(GTK_TREE_VIEW (self->tView), GTK_TREE_MODEL (self->lStore));
+	gtk_container_add 							(GTK_CONTAINER (scrollWin), self->tView);
+	g_signal_connect							(self->tView, "row-activated", G_CALLBACK (video_selected), self);
+	gtk_widget_show 							(self->tView);
+	gtk_widget_show								(scrollWin);
+	gtk_box_pack_start							(GTK_BOX(self->box1), scrollWin, TRUE, TRUE, 2);
+}
+
+GDataMediaThumbnail *
+choose_best_thumbnail (GList *thumbnails, gint ideal_size)
+{
+	gint delta = G_MININT;
+	GDataMediaThumbnail *thumbnail;
+	for (; thumbnails != NULL; thumbnails = thumbnails->next) {
+		gint new_delta;
+		GDataMediaThumbnail *current = (GDataMediaThumbnail *) thumbnails->data;
+		new_delta = gdata_media_thumbnail_get_width (current) - ideal_size;
+		if (delta == 0) {
+			break;
+		} else if ((delta == G_MININT)
+		|| (delta < 0 && new_delta > delta)
+		|| (delta > 0 && new_delta < delta)) {
+			delta = new_delta;
+			thumbnail = current;
+		}
+	}
+	return thumbnail;
+}
+
+static void
+find_pictures  (GDataEntry *entry, guint entry_key, guint entry_count, ScrapPicSearch *self)
+{
+	GList 				*thumbnails;
+	GDataMediaThumbnail	*thumbnail;
+	GFileInputStream	*input_stream;
+	
+	gtk_list_store_append	(self->lStore, &(self->iter));
+	gtk_list_store_set		(self->lStore, &(self->iter),
+							 P_COL_PIXBUF, NULL,
+							 P_COL_TITLE,  self->title,
+							 P_COL_USER,   self->user,
+							 P_COL_PIC,	   entry, -1);
+	thumbnails		= gdata_picasaweb_file_get_thumbnails (GDATA_PICASAWEB_FILE (entry));
+	thumbnail		= choose_best_thumbnail (thumbnails, THUMBNAIL_WIDTH);
+	if (thumbnail != NULL) {
+		GFile *thumbnail_file;
+		thumbnail_file 	= g_file_new_for_uri 					(gdata_media_thumbnail_get_uri (thumbnail));
+		input_stream   	= g_file_read							(thumbnail_file, NULL, NULL);
+		self->thumbnail	= gdk_pixbuf_new_from_stream_at_scale 	(G_INPUT_STREAM (input_stream), THUMBNAIL_WIDTH, -1,
+																 TRUE, NULL, NULL);
+		gtk_list_store_set 	(self->lStore, &(self->iter), P_COL_PIXBUF, self->thumbnail, -1); /* we can now set the thumbnail ;) */
+		g_object_unref		(thumbnail_file);
+	}
+	gdata_query_set_q (self->query, NULL);
+}
+
+
+static void
+p_query_element (GDataEntry *entry, guint entry_key, guint entry_count, ScrapPSearch *self)
+{
+	GError				*error=NULL;
+	ScrapPicSearch		*picture;
+	picture = self->pic;
+	picture->title				= gdata_entry_get_title	(entry);
+	picture->query 				= picture->search_data->query;
+	picture->user				= self->user;
+	gdata_query_set_q 					(picture->query, picture->title);
+	gdata_picasaweb_service_query_files (picture->search_data->service,
+										 GDATA_PICASAWEB_ALBUM (entry),
+										 picture->query,
+										 NULL,
+										 (GDataQueryProgressCallback) find_pictures,
+										 picture, &error);
+	if (error != NULL) {
+		g_print ("whoops, somebody raised an error!\n%s", error->message);
+		g_error_free (error);
+	}
+}
+
+static void
+p_text_callback (GtkWidget *widget, ScrapPSearch *self)
+{
+	GError *error 	= NULL;
+	self->user		= gtk_entry_get_text 			(GTK_ENTRY (self->user_entry));
+	self->pic->lStore = gtk_list_store_new (P_N_COLS, GDK_TYPE_PIXBUF,
+											G_TYPE_STRING,
+											G_TYPE_STRING,
+											GDATA_TYPE_ENTRY);
+	self->pic->tView	= gtk_tree_view_new ();
+	gdata_picasaweb_service_query_all_albums	(self->service, self->query,
+												 self->user, NULL,
+											    (GDataQueryProgressCallback) p_query_element,
+												 self, &error);
+	if (error != NULL) {
+		g_print ("someone raised an error\n%s\n",error->message);
+		g_error_free (error);
+	}
+	p_display_tree (self->pic);
+}
+
+
+/* ran as a callback for each individual element queried
+ * it takes the video found, a unique entry_key and entry_count and the data structure as arguments
+ * parts of this function were inspired (or simply taken) from the totem youtube plugin */
+static void
+yt_query_element (GDataEntry *entry, guint entry_key, guint entry_count, ScrapYTSearch *self)
+{
+	GList 				*thumbnails;
+	GDataMediaThumbnail *thumbnail;
+	gchar				*title; /* the video's title */
+	gchar				*uri;   /* the video's URI */
+	GFileInputStream	*input_stream; /* this will be used to make a pixbuf to store the thumbnail */
+	title	= gdata_entry_get_title 				(entry); /* self-explanatory, I hope */
+	uri		= gdata_youtube_video_get_player_uri	(GDATA_YOUTUBE_VIDEO (entry)); /* ditto */
+	g_print ("%s %s", title, uri);
+	gtk_list_store_append (self->lStore, &(self->iter)); /* make a new entry for this vid */
+	gtk_list_store_set	  (self->lStore, &(self->iter),
+						   COL_PIXBUF, NULL, /* this will be set in a few moments */
+						   COL_TITLE, title,
+						   COL_VIDEO, entry,
+						   -1);
+	/* get a GList of thumbnails for the vid */
+	thumbnails = gdata_youtube_video_get_thumbnails (GDATA_YOUTUBE_VIDEO (entry)); 
+	thumbnail  = choose_best_thumbnail (thumbnails, THUMBNAIL_WIDTH);
+	if (thumbnail != NULL) {
+		GFile *thumbnail_file;
+		thumbnail_file 	= g_file_new_for_uri 					(gdata_media_thumbnail_get_uri (thumbnail));
+		input_stream   	= g_file_read							(thumbnail_file, NULL, NULL);
+		self->thumbnail	= gdk_pixbuf_new_from_stream_at_scale 	(G_INPUT_STREAM (input_stream), THUMBNAIL_WIDTH, -1,
+																 TRUE, NULL, NULL);
+		gtk_list_store_set 	(self->lStore, &(self->iter), COL_PIXBUF, self->thumbnail, -1); /* we can now set the thumbnail ;) */
+		g_object_unref		(thumbnail_file);
+	}
+}
+
+
+static void
+yt_text_callback (GtkWidget *widget, ScrapYTSearch *self)
+{
+	self->txt = gtk_entry_get_text (GTK_ENTRY (self->txt_entry));
+	gdata_query_set_q	 				(self->query, self->txt);	/* set the string we'll be searching for in youtube */
+	/* do the actual query, running yt_query_element for each object found */
+	gdata_youtube_service_query_videos 	(self->service, self->query, NULL, (GDataQueryProgressCallback) yt_query_element, self, NULL);
+	yt_display_tree (self); /* run yt_display_tree to show the results */
+}
+
+
+static void
+start_new_picasa_search (GtkWidget *widget, ScrapData *first)
+{
+	ScrapPSearch 				*self;
+	ScrapPicSearch				*picture;
+	self = first->p_search;
+	picture 					= first->pic_search;
+	picture->search_data 		= self;
+	picture->search_data->pic	= picture;
+	picture->main_data			= self->main_data;
+	g_assert			 (GDATA_IS_PICASAWEB_SERVICE (self->service));
+	gtk_list_store_clear (self->pic->lStore);
+	
+	self->window = gtk_window_new 	(GTK_WINDOW_TOPLEVEL);
+	gtk_window_resize				(GTK_WINDOW (self->window), 400, 400);
+	g_signal_connect 				(self->window, "destroy", G_CALLBACK (gtk_widget_destroy), NULL);
+	g_signal_connect_swapped 		(self->window, "delete-event", G_CALLBACK (gtk_widget_destroy), NULL);
+	
+	/* our two boxes */
+	
+	self->box1	 = gtk_vbox_new	  	(FALSE, 10); /* this box contains everything in our window */
+	gtk_container_add 				(GTK_CONTAINER (self->window), self->box1);
+	self->box2	 = gtk_hbox_new	  	(FALSE,  2);
+	
+	/* search bar */
+	
+	self->user_entry = gtk_entry_new ();
+	gtk_entry_set_text 				(GTK_ENTRY (self->user_entry), "user to search for");
+	g_signal_connect				(self->button, "activated", G_CALLBACK (p_text_callback), self);
+	gtk_box_pack_start 				(GTK_BOX(self->box2), self->user_entry, TRUE, TRUE, 0);
+	gtk_widget_show    				(self->user_entry);
+	
+	/* button */
+		
+			
+	self->button = gtk_button_new_with_label ("search");
+	g_signal_connect	(self->button, "clicked", G_CALLBACK (p_text_callback), self);
+	gtk_box_pack_start 	(GTK_BOX (self->box2), self->button, FALSE, FALSE, 0);
+	gtk_widget_show		(self->button);
+	
+	gtk_box_pack_end (GTK_BOX (self->box1), self->box2, FALSE, FALSE, 0); /* pack the box with the button and search bar */
+	gtk_widget_show (self->box2);
+	
+	gtk_widget_show (self->box1);
+	gtk_widget_show (self->window);
+}
+
+	
+
+static void
+start_new_youtube_search (GtkWidget *widget, ScrapData *first) /* *first is a pointer we use to talk to the main window */
+{
+	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 */
+	self = first->yt_search;
+
+	gtk_list_store_clear 				(self->lStore); /* clear it out */
+	self->tView  = gtk_tree_view_new 	();
+	/* window stuff */
+	self->window = gtk_window_new	(GTK_WINDOW_TOPLEVEL);
+	gtk_window_resize				(GTK_WINDOW (self->window), 400, 400);
+	g_signal_connect 				(self->window, "destroy", G_CALLBACK (gtk_widget_destroy), NULL);
+	g_signal_connect_swapped 		(self->window, "delete-event", G_CALLBACK (gtk_widget_destroy), NULL);
+	
+	/* our two boxes */
+	
+	self->box1	 = gtk_vbox_new	  	(FALSE, 10); /* this box contains everything in our window */
+	gtk_container_add 				(GTK_CONTAINER (self->window), self->box1);
+	self->box2	 = gtk_hbox_new	  	(FALSE,  2);
+	
+	/* search bar */
+	
+	self->txt_entry = gtk_entry_new ();
+	g_signal_connect 				(self->txt_entry, "activate", G_CALLBACK (yt_text_callback), self);
+	gtk_box_pack_start 				(GTK_BOX(self->box2), self->txt_entry, TRUE, TRUE, 0);
+	gtk_widget_show    				(self->txt_entry);
+	
+	/* button */
+	
+	self->button = gtk_button_new_with_label 	("search");
+	g_signal_connect 							(self->button, "clicked", G_CALLBACK (yt_text_callback), self);
+	gtk_box_pack_start 							(GTK_BOX (self->box2), self->button, TRUE, TRUE, 0);
+	gtk_widget_show								(self->button);
+	
+	gtk_box_pack_end (GTK_BOX (self->box1), self->box2, FALSE, FALSE, 0); /* pack the box with the button and search bar */
+	
+	gtk_widget_show (self->box2);
+	gtk_widget_show (self->box1);
+	gtk_widget_show (self->window);
+
+
+	/* everything else is implemented somewhere else */
+}
+
+
+static void
+properties_set (GtkWidget *widget, ScrapProps *self)
+{
+	self->main_data->username = gtk_entry_get_text (GTK_ENTRY(self->username_entry));
+	self->main_data->password = gtk_entry_get_text (GTK_ENTRY(self->password_entry));
+	/* authenticate on youtube */
+	{
+		GError *error = NULL;
+		gdata_service_authenticate (GDATA_SERVICE (self->main_data->yt_search->service),
+									self->main_data->username,
+									self->main_data->password,
+									NULL, &error);
+		if (error != NULL) { /* we show this to the user in case he mistyped his password */
+			GtkWidget *label;
+			label = gtk_label_new (error->message);
+			gtk_widget_show (label);
+			gtk_box_pack_end (GTK_BOX (self->box1), label, FALSE, FALSE, 0);
+			g_print("error\n%s\n", error->message);
+			g_error_free(error);
+		}
+	}	
+	/* authenticate on picasa (no time for fun and games, so we assume he's got the same account on both services) */
+	{
+		GError *error = NULL;
+		gdata_service_authenticate (GDATA_SERVICE (self->main_data->p_search->service),
+									self->main_data->username,
+									self->main_data->password,
+									NULL, &error);
+		if (error != NULL) {
+			GtkWidget *label;
+			label = gtk_label_new (error->message);
+			gtk_widget_show (label);
+			gtk_box_pack_end (GTK_BOX (self->box1), label, FALSE, FALSE, 0);
+			g_print("error\n%s\n", error->message);
+			g_error_free(error);
+		}
+	}
+
+	
+	/* if the username and password are changed, we re-authenticate */
+	self->main_data->title	  = gtk_entry_get_text (GTK_ENTRY(self->title_entry));
+	gtk_window_set_title(GTK_WINDOW (self->main_data->window), self->main_data->title);
+	gtk_widget_destroy (self->window);
+}
+
+static void
+properties_show (GtkWidget *widget, ScrapData *first)
+{
+	ScrapProps	*self;
+	self			= g_slice_new (struct _ScrapProps);
+	self->main_data	= first;
+	self->window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+	gtk_window_resize (GTK_WINDOW (self->window), 250, 250);
+	g_signal_connect (self->window, "destroy", G_CALLBACK (gtk_widget_destroy), NULL);
+	g_signal_connect (self->window, "delete-event", G_CALLBACK (gtk_widget_destroy), NULL);
+	
+	self->box1	= gtk_vbox_new (FALSE, 3);
+	self->box2 	= gtk_hbox_new (FALSE, 10);
+	
+	self->label = gtk_label_new ("username");
+	gtk_widget_show		(self->label);
+	gtk_box_pack_start 	(GTK_BOX (self->box2), self->label, TRUE, TRUE, 0);
+	self->label = gtk_label_new ("password");
+	gtk_widget_show		(self->label);
+	gtk_box_pack_start 	(GTK_BOX (self->box2), self->label, TRUE, TRUE, 0);
+	self->label = gtk_label_new ("title");
+	gtk_widget_show		(self->label);
+	gtk_box_pack_start	(GTK_BOX (self->box2), self->label, TRUE, TRUE, 0);
+	gtk_widget_show		(self->box2);
+	gtk_box_pack_start 	(GTK_BOX (self->box1), self->box2, FALSE, FALSE, 0);
+	
+	self->box2 = gtk_hbox_new (FALSE, 10);
+	self->username_entry = gtk_entry_new ();
+	
+	if (self->main_data->username != NULL)
+		gtk_entry_set_text (GTK_ENTRY(self->username_entry), self->main_data->username);
+	
+	gtk_widget_show	   (self->username_entry);
+	gtk_box_pack_start (GTK_BOX (self->box2), self->username_entry, TRUE, TRUE, 0);
+	
+	self->password_entry = gtk_entry_new ();
+	gtk_entry_set_visibility (GTK_ENTRY (self->password_entry), FALSE);
+	
+	if (self->main_data->password != NULL)
+		gtk_entry_set_text (GTK_ENTRY(self->password_entry), self->main_data->password);
+	
+	gtk_widget_show	   (self->password_entry);
+	gtk_box_pack_start (GTK_BOX (self->box2), self->password_entry, TRUE, TRUE, 0);
+	
+	self->title_entry = gtk_entry_new ();
+	if (self->main_data->title != NULL)
+		gtk_entry_set_text (GTK_ENTRY (self->title_entry), self->main_data->title);
+	
+	gtk_widget_show (self->title_entry);
+	gtk_box_pack_start (GTK_BOX (self->box2), self->title_entry, TRUE, TRUE, 0);
+	
+	gtk_box_pack_start 	(GTK_BOX (self->box1), self->box2, FALSE, FALSE, 0);
+	gtk_widget_show		(self->box2);
+	self->button = gtk_button_new_with_label ("Ok");
+	g_signal_connect 	(self->button, "clicked", G_CALLBACK (properties_set), self);
+	gtk_widget_show		(self->button);
+	gtk_box_pack_start 	(GTK_BOX (self->box1), self->button, FALSE, FALSE, 0);
+	gtk_widget_show		(self->box1);
+	gtk_container_add	(GTK_CONTAINER (self->window), self->box1);
+	gtk_widget_show		(self->window);
+}
+
+static void
+select_file (GtkWidget *widget, ScrapPUpload *self)
+{
+	GFile *file;
+	GError *error = NULL;
+	file = g_file_new_for_path(gtk_file_selection_get_filename (GTK_FILE_SELECTION(self->file_dialog)));
+	/* upload our file, using the service we've set up, and metadata
+	 * set up in upload ()
+	 * no album is specified, but that should be easy to add */
+	self->file=gdata_picasaweb_service_upload_file (self->main_data->p_search->service,
+										 NULL, /* for now uploading to drop box */
+										 self->file, file, NULL, &error);
+	if (error != NULL) {
+		g_print ("error: %s\n", error->message);
+	}
+	g_free (error);
+	/* since the upload blocks, it's safe to assume the widget won't
+	 * be destroyed until we're done */
+	gtk_widget_destroy (self->file_dialog);
+}
+										 
+static void
+got_name (GtkWidget *widget, ScrapPUpload *self)
+{
+	gdata_entry_set_title 	(GDATA_ENTRY (self->file),
+							 gtk_entry_get_text (GTK_ENTRY (self->name)));
+	gdata_entry_set_summary	(GDATA_ENTRY (self->file),
+							 gtk_entry_get_text (GTK_ENTRY (self->description)));
+	gtk_widget_destroy 	(self->dialog);
+	gtk_widget_show		(self->file_dialog);
+}
+	
+static void
+upload (GtkWidget *widget, ScrapData *first)
+{
+	ScrapPUpload 	*self;
+	GtkWidget		*label;
+	label = gtk_label_new ("Enter photo name and description");
+	self = first->p_upload;
+	self->file_dialog = gtk_file_selection_new ("upload");
+	/* we make a new file, without an id (it will be assigned automatically later on) */
+	self->file  = gdata_picasaweb_file_new (NULL);
+	/* dialog to get the file's name and description */
+	self->dialog = gtk_dialog_new();
+	
+	gtk_widget_show (label);
+	gtk_box_pack_start	(GTK_BOX (GTK_DIALOG(self->dialog)->vbox),
+						 label, FALSE, FALSE, 0);
+	
+	self->name	= gtk_entry_new ();
+	g_signal_connect 	(self->name, "activate", G_CALLBACK (got_name), self);
+	gtk_widget_show  	(self->name);
+	gtk_box_pack_start 	(GTK_BOX (GTK_DIALOG(self->dialog)->action_area),
+						 self->name, TRUE, TRUE, 0);
+	
+	self->description = gtk_entry_new ();
+	g_signal_connect 	(self->description, "activate", G_CALLBACK (got_name), self);
+	gtk_widget_show  	(self->description);
+	gtk_box_pack_start 	(GTK_BOX (GTK_DIALOG (self->dialog)->action_area),
+						 self->description, TRUE, TRUE, 0);
+	
+	gtk_widget_show		(self->dialog);
+	g_signal_connect 	(self->file_dialog, "destroy", G_CALLBACK (gtk_widget_destroy), NULL);
+	g_signal_connect 	(GTK_FILE_SELECTION(self->file_dialog)->ok_button, "clicked",
+						 G_CALLBACK (select_file), self);
+	
+	g_signal_connect_swapped (GTK_FILE_SELECTION (self->file_dialog)->cancel_button,
+							  "clicked", G_CALLBACK (gtk_widget_destroy),
+							  self->file_dialog);
+}
+
+int
+main(int argc, char **argv)
+{
+	ScrapData 		*scrapbook;
+	ScrapPSearch 	*picasaSearch;
+	ScrapYTSearch	*youtubeSearch;
+	ScrapPicSearch	*photoSearch;
+	ScrapPUpload	*fUpload;
+	scrapbook = g_slice_new (struct _ScrapData);
+	scrapbook->title			= NULL;
+	scrapbook->max_rows			= 5;
+	g_type_init ();
+	gtk_init	(&argc, &argv);
+	
+	scrapbook->currentCol 							= 0;
+	scrapbook->currentRow[scrapbook->currentCol]	= 0;
+	
+	scrapbook->lStore   = gtk_list_store_new (ORIG_N_COLS, GDK_TYPE_PIXBUF, G_TYPE_STRING, GDATA_TYPE_ENTRY);
+	scrapbook->window 	= gtk_window_new 	(GTK_WINDOW_TOPLEVEL);
+	g_signal_connect (scrapbook->window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
+	g_signal_connect (scrapbook->window, "delete-event", G_CALLBACK (gtk_main_quit), NULL);
+	
+	youtubeSearch 				= g_slice_new (struct _ScrapYTSearch); /* get some memory for the structure */
+	youtubeSearch->txt	 		= NULL;
+	scrapbook->yt_search 		= youtubeSearch;
+	youtubeSearch->main_data 	= scrapbook;
+	/* create a new query, without any search text, starting at 0, and search only MAX_RESULTS results */
+	youtubeSearch->query = gdata_query_new_with_limits (NULL, 0, MAX_RESULTS);
+	/* 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) */
+	youtubeSearch->service = gdata_youtube_service_new (DEVELOPER_KEY, "");
+	/* create a new list store and tree to show the user the results
+	 * 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) */
+	youtubeSearch->lStore = gtk_list_store_new 	(N_COLS, GDK_TYPE_PIXBUF, G_TYPE_STRING, GDATA_TYPE_ENTRY);
+
+	picasaSearch 				= g_slice_new (struct _ScrapPSearch);
+	scrapbook->p_search 		= picasaSearch;
+	picasaSearch->main_data 	= scrapbook;
+	picasaSearch->query 		= gdata_query_new_with_limits (NULL, 0, MAX_RESULTS);
+	picasaSearch->service 		= gdata_picasaweb_service_new ("");
+
+	photoSearch					= g_slice_new (struct _ScrapPicSearch);
+	scrapbook->p_search->pic	= photoSearch;
+	scrapbook->pic_search		= photoSearch;
+	
+	fUpload						= g_slice_new (struct _ScrapPUpload);
+	scrapbook->p_upload			= fUpload;
+	fUpload->main_data			= scrapbook;
+	
+	gtk_window_resize(GTK_WINDOW (scrapbook->window), 350, 150);
+	scrapbook->box1		= gtk_hbox_new		(FALSE, 0);
+	scrapbook->box2		= gtk_vbox_new		(FALSE, 2);
+	scrapbook->table	= gtk_table_new		(5,5,FALSE);
+	
+	scrapbook->button = gtk_button_new_with_label ("Add You Tube Video");	
+	g_signal_connect 	(scrapbook->button, "clicked", G_CALLBACK (start_new_youtube_search), scrapbook);
+	gtk_box_pack_start	(GTK_BOX (scrapbook->box2), scrapbook->button, FALSE, FALSE, 0);
+	gtk_widget_show		(scrapbook->button);
+		
+	scrapbook->button = gtk_button_new_with_label ("Add Picasa Photo");
+	g_signal_connect	(scrapbook->button,"clicked", G_CALLBACK (start_new_picasa_search), scrapbook);
+	gtk_box_pack_start	(GTK_BOX (scrapbook->box2), scrapbook->button, FALSE, FALSE, 0);
+	gtk_widget_show 	(scrapbook->button);
+	
+	scrapbook->button = gtk_button_new_with_label ("Properties");
+	g_signal_connect	(scrapbook->button, "clicked", G_CALLBACK (properties_show), scrapbook);
+	gtk_box_pack_start	(GTK_BOX (scrapbook->box2), scrapbook->button, FALSE, FALSE, 0);
+	gtk_widget_show		(scrapbook->button);
+	
+	scrapbook->button = gtk_button_new_with_label ("Upload picture to picasa web");
+	g_signal_connect	(scrapbook->button, "clicked", G_CALLBACK (upload), scrapbook);
+	gtk_box_pack_start 	(GTK_BOX (scrapbook->box2), scrapbook->button, FALSE, FALSE, 0);
+	gtk_widget_show		(scrapbook->button);
+	
+	gtk_widget_show		(scrapbook->box2);
+	gtk_box_pack_start	(GTK_BOX (scrapbook->box1), scrapbook->box2, FALSE, FALSE, 5);
+	gtk_box_pack_start	(GTK_BOX (scrapbook->box1), scrapbook->table, TRUE, TRUE, 0);
+	gtk_widget_show		(scrapbook->table);
+	gtk_widget_show		(scrapbook->box1);
+	gtk_container_add	(GTK_CONTAINER (scrapbook->window), scrapbook->box1);
+	gtk_widget_show		(scrapbook->window);
+	gtk_main			();
+	return 0;
+}
diff --git a/demos/scrapbook/scrapdata.h b/demos/scrapbook/scrapdata.h
new file mode 100644
index 0000000..a2f878e
--- /dev/null
+++ b/demos/scrapbook/scrapdata.h
@@ -0,0 +1,182 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <gtk/gtk.h>
+#include <gdata/gdata.h>
+#include <glib.h>
+#include <glib-object.h>
+#define DEVELOPER_KEY "AI39si5MkSF-0bzTmP5WETk1D-Z7inHaQJzX13PeG_5Uzeu8mz3vo40cFoqnxjejB-UqzYFrqzOSlsqJvHuPNEGqdycqnPo30A"
+#define THUMBNAIL_WIDTH 180
+#define MAX_RESULTS 	10
+
+/* how this works is that there's a struct for every window opened
+ * they contain that individual window's data
+ * and every one of them (except for scrap data, which is for the main window)
+ * has a pointer to the one for the main window called main_data */
+
+enum {
+	COL_PIXBUF,
+	COL_TITLE,
+	COL_VIDEO,
+	N_COLS
+};
+
+enum {
+	P_COL_PIXBUF,
+	P_COL_TITLE,
+	P_COL_USER,
+	P_COL_PIC,
+	P_N_COLS
+};
+
+
+enum {
+	ORIG_COL_PIXBUF,
+	ORIG_COL_TITLE,
+	ORIG_COL_ENTRY,
+	ORIG_N_COLS
+};
+
+typedef struct _ScrapYTSearch ScrapYTSearch;
+typedef struct _ScrapPSearch  ScrapPSearch;
+typedef struct _ScrapPUpload  ScrapPUpload;
+
+typedef struct _ScrapData {
+	GtkWidget		*window;
+	GtkWidget		*button;
+	gint			currentCol;
+	gint			currentRow[5];
+	GtkWidget		*box1, *box2;
+	GtkWidget		*table;
+	GtkWidget		*scrollWindow;
+	gchar			*title;
+	ScrapYTSearch	*yt_search;
+	ScrapPSearch	*p_search;
+	ScrapPSearch	*pic_search;
+	ScrapPUpload	*p_upload;
+	gint			max_rows;
+	gchar			*username;
+	gchar			*password;
+	GtkListStore	*lStore;
+	GtkTreeIter		iter;
+} ScrapData;
+struct _ScrapPUpload {
+	ScrapData			*main_data;
+	GtkWidget			*file_dialog;
+	GDataPicasaWebFile	*file;
+	GtkWidget			*dialog;
+	GtkWidget			*name;
+	GtkWidget			*description;
+};
+
+typedef struct _ScrapPicSearch { /* for finding pictures */
+	gchar					*title;
+	gchar					*uri;
+	gchar					*user;
+	GdkPixbuf				*thumbnail;
+	ScrapData				*main_data;
+	ScrapPSearch			*search_data;
+	GDataQuery				*query;
+	GDataPicasaWebFile		*file;
+	GtkListStore			*lStore;
+	GtkTreeIter				iter;
+	GtkWidget				*tView;
+} ScrapPicSearch;
+
+struct _ScrapYTSearch { /* youtube search data */
+	GtkWidget 			*txt_entry;
+	gchar 	  			*txt;
+	GtkWidget			*window;
+	GDataQuery		 	*query;
+	GDataYouTubeService	*service;
+	gchar				*title;
+	gchar				*uri;
+	GdkPixbuf			*thumbnail;
+	GtkWidget 			*box1, *box2;
+	ScrapData			*main_data; /* <- points to a structure containing main vars */
+	GtkWidget			*button;
+	GtkListStore		*lStore;
+	GtkTreeIter			iter;
+	GtkWidget			*tView;
+};
+
+struct _ScrapPSearch { /* for finding albums */
+	GtkWidget				*window;
+	GDataQuery				*query;
+	GDataPicasaWebService	*service;
+	gchar					*title;
+	gchar					*uri;
+	GdkPixbuf				*thumbnail;
+	GtkWidget				*box1, *box2;
+	ScrapData				*main_data;
+	GtkWidget				*button;
+	GtkWidget				*user_entry;
+	gchar					*user;
+	ScrapPicSearch			*pic;
+};
+
+typedef struct _ScrapProps {
+	GtkWidget	*window;
+	GtkWidget	*button;
+	GtkWidget	*box1, *box2;
+	GtkWidget	*label;
+	GtkWidget	*username_entry, *password_entry, *title_entry;
+	ScrapData	*main_data;
+} ScrapProps;
+
+
+static void
+open_in_web_browser (GtkWidget *widget, gchar *uri);
+
+static void
+picture_selected (GtkTreeView *tree, GtkTreePath *path, GtkTreeViewColumn *column, ScrapPicSearch *self);
+
+static void
+video_selected (GtkTreeView *tree, GtkTreePath *path, GtkTreeViewColumn *column, ScrapYTSearch *self);
+
+static void
+p_display_tree (ScrapPicSearch *self);
+
+static void
+yt_display_tree (ScrapYTSearch *self);
+
+GDataMediaThumbnail *
+choose_best_thumbnail (GList *thumbnails, gint ideal_size);
+
+static void
+find_pictures  (GDataEntry *entry, guint entry_key, guint entry_count, ScrapPicSearch *self);
+
+static void
+p_query_element (GDataEntry *entry, guint entry_key, guint entry_count, ScrapPSearch *self);
+
+static void
+p_text_callback (GtkWidget *widget, ScrapPSearch *self);
+
+static void
+yt_query_element (GDataEntry *entry, guint entry_key, guint entry_count, ScrapYTSearch *self);
+
+static void
+yt_text_callback (GtkWidget *widget, ScrapYTSearch *self);
+
+static void
+start_new_picasa_search (GtkWidget *widget, ScrapData *first);
+
+static void
+start_new_youtube_search (GtkWidget *widget, ScrapData *first);
+
+static void
+properties_set (GtkWidget *widget, ScrapProps *self);
+
+static void
+properties_show (GtkWidget *widget, ScrapData *first);
+
+static void
+select_file (GtkWidget *widget, ScrapPUpload *self);
+
+static void
+got_name (GtkWidget *widget, ScrapPUpload *self);
+
+static void
+upload (GtkWidget *widget, ScrapData *first);
+
+
+



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]