[ease] Improved Flickr search.



commit 64122deeacd5b55d54317c9d21c6ebbbc91108ca
Author: Nate Stedman <natesm gmail com>
Date:   Fri Oct 15 15:02:54 2010 -0400

    Improved Flickr search.
    
    - Added extra_widget to PluginImportService, which allows services
      to specify an additional widget, which will display extra settings.
    
    - Implemented this function in FlickrService, to allow the user to
      choose between different CC license parameters.
    
    - More documentation

 data/ui/import-widget.ui                  |   19 +++-
 ease-core/ease-plugin-import-service.vala |   57 ++++++++++-
 ease/ease-import-flickr-media.vala        |   17 +++
 ease/ease-import-flickr-service.vala      |  151 ++++++++++++++++++-----------
 ease/ease-import-oca-service.vala         |    2 -
 ease/ease-import-widget.vala              |   32 ++++++
 6 files changed, 211 insertions(+), 67 deletions(-)
---
diff --git a/data/ui/import-widget.ui b/data/ui/import-widget.ui
index 7d941a7..ddde9f2 100644
--- a/data/ui/import-widget.ui
+++ b/data/ui/import-widget.ui
@@ -1,4 +1,4 @@
-<?xml version="1.0"?>
+<?xml version="1.0" encoding="UTF-8"?>
 <interface>
   <requires lib="gtk+" version="2.16"/>
   <!-- interface-naming-policy project-wide -->
@@ -23,7 +23,7 @@
                   <object class="GtkEntry" id="search">
                     <property name="visible">True</property>
                     <property name="can_focus">True</property>
-                    <property name="invisible_char">&#x2022;</property>
+                    <property name="invisible_char">â?¢</property>
                     <property name="secondary_icon_stock">gtk-clear</property>
                     <property name="secondary_icon_sensitive">True</property>
                   </object>
@@ -122,16 +122,27 @@
               </packing>
             </child>
             <child>
-              <object class="GtkHBox" id="hbox2">
+              <object class="GtkHBox" id="bottom-hbox">
                 <property name="visible">True</property>
                 <property name="spacing">4</property>
                 <child>
-                  <object class="GtkProgressBar" id="progress-bar"/>
+                  <object class="GtkAlignment" id="extra-alignment">
+                    <property name="visible">True</property>
+                    <child>
+                      <placeholder/>
+                    </child>
+                  </object>
                   <packing>
                     <property name="position">0</property>
                   </packing>
                 </child>
                 <child>
+                  <object class="GtkProgressBar" id="progress-bar"/>
+                  <packing>
+                    <property name="position">2</property>
+                  </packing>
+                </child>
+                <child>
                   <object class="GtkButton" id="close">
                     <property name="label">gtk-close</property>
                     <property name="visible">True</property>
diff --git a/ease-core/ease-plugin-import-service.vala b/ease-core/ease-plugin-import-service.vala
index 29cf13b..90a3d45 100644
--- a/ease-core/ease-plugin-import-service.vala
+++ b/ease-core/ease-plugin-import-service.vala
@@ -47,11 +47,38 @@ public abstract class Ease.Plugin.ImportService : GLib.Object
 	 */
 	private float list_size;
 	
+	/**
+	 * Emitted when the search begins.
+	 */
 	public signal void started();
+	
+	/**
+	 * Emitted when the search completes.
+	 */
 	public signal void proxy_call_complete();
+	
+	/**
+	 * Emitted if no results are found. This signal is the alterative to
+	 * { link loading_started}.
+	 */
 	public signal void no_results();
+	
+	/**
+	 * Emitted when image previews begin downloading. This signal is the
+	 * alternative to { link no_results}.
+	 */
 	public signal Gtk.IconView loading_started();
+	
+	/**
+	 * Emitted when progress is made in loading the image previews.
+	 *
+	 * @param progress The current progress.
+	 */
 	public signal void loading_progress(double progress);
+	
+	/**
+	 * Emitted when the loading of image previews is complete.
+	 */
 	public signal void loading_complete();
 	
 	/**
@@ -93,6 +120,11 @@ public abstract class Ease.Plugin.ImportService : GLib.Object
 		images_list.add(media);
 	}
 	
+	/**
+	 * Runs a search with this service.
+	 *
+	 * @param search The search string to use.
+	 */
 	public void run(string search)
 	{
 		// create the rest proxy call
@@ -107,6 +139,23 @@ public abstract class Ease.Plugin.ImportService : GLib.Object
 	}
 	
 	/**
+	 * This virtual function should be overridden by services that require
+	 * more advanced control than a simple string search.
+	 *
+	 * For example, it can be used to select different types of Creative
+	 * Commons licenses. By default, it returns null.
+	 *
+	 * In order to properly fit into Ease's current search window layout, 
+	 * this should be a relatively short and narrow widget. One or two
+	 * checkboxes is ideal, any more will take up too much space (consider a
+	 * popup window if more space is required).
+	 */
+	public virtual Gtk.Widget? extra_widget()
+	{
+		return null;
+	}
+	
+	/**
 	 * Signal handler for Rest.ProxyCall completion.
 	 *
 	 * @param call The completed Rest.ProxyCall.
@@ -203,11 +252,11 @@ public abstract class Ease.Plugin.ImportService : GLib.Object
 	 *
 	 * @param uri The URI to load from.
 	 */
-	private Gdk.Pixbuf? gdk_pixbuf_from_uri (string uri) {
-
-		File file = File.new_for_uri (uri);
+	private Gdk.Pixbuf? gdk_pixbuf_from_uri(string uri)
+	{
+		File file = File.new_for_uri(uri);
 		FileInputStream filestream;
-		try { filestream = file.read (null); }
+		try { filestream = file.read(null); }
 		catch (Error e)
 		{
 			filestream = null;
diff --git a/ease/ease-import-flickr-media.vala b/ease/ease-import-flickr-media.vala
index 76d3396..563e2f6 100644
--- a/ease/ease-import-flickr-media.vala
+++ b/ease/ease-import-flickr-media.vala
@@ -1,3 +1,20 @@
+/*  Ease, a GTK presentation application
+    Copyright (C) 2010 Nate Stedman
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
 internal class Ease.FlickrMedia : Plugin.ImportMedia
 {
 	internal string title;
diff --git a/ease/ease-import-flickr-service.vala b/ease/ease-import-flickr-service.vala
index c680567..7940aaf 100644
--- a/ease/ease-import-flickr-service.vala
+++ b/ease/ease-import-flickr-service.vala
@@ -1,7 +1,3 @@
-using Rest;
-using Json;
-using Gtk;
-
 /*
   TODO :
   - escaping the description tags (or show the markup maybe?)
@@ -17,13 +13,25 @@ using Gtk;
 
 public class Ease.FlickrService : Plugin.ImportService {
 
-	/* Flickr stuff */
+	// Flickr stuff
 	private const string api_key = "17c40bceda03e0d6f947b001e7c62058";
 	private const string secret = "a7c16179a409418b";
+	private const string URL_FORMAT =
+		"http://farm%i.static.flickr.com/%s/%s_%s.jpg";;
 
-	/* Json parser */
+	// Json parser
 	private Json.Parser parser = new Json.Parser();
 	
+	// CC license filter
+	private Gtk.CheckButton share_alike;
+	private Gtk.CheckButton for_commercial;
+	
+	// CC license IDs - No derivatives doesn't make sense so we don't have them
+	private const string CC_BY = "4,";
+	private const string CC_BY_NC = "2,";
+	private const string CC_BY_NC_SA = "1,";
+	private const string CC_BY_SA = "5,";
+	
 	public override Rest.Proxy create_proxy()
 	{
 		return new Rest.FlickrProxy(api_key, secret);
@@ -31,79 +39,108 @@ public class Ease.FlickrService : Plugin.ImportService {
 	
 	public override Rest.ProxyCall create_call(Rest.Proxy proxy, string search)
 	{
+		// create a string of licenses
+		string licenses;
+		if (share_alike.active)
+		{
+			licenses = CC_BY_SA;
+			if (!for_commercial.active) licenses += CC_BY_NC_SA;
+		}
+		else
+		{
+			licenses = CC_BY;
+			if (!for_commercial.active) licenses += CC_BY_NC;
+		}
+		
 		var call = proxy.new_call ();
-		call.set_function ("flickr.photos.search");
-		call.add_params ("tags", search,
-						 "tag_mode", "all",
-						 "per_page", "10",
-						 "format", "json",
-						 "sort", "relevance",
-						 /* Flickr adds a function around the JSon payload,
-							setting 'nojsoncallback' disable that : we get
-							only plain JSON. */
-						 "nojsoncallback", "1",
-						 /* Extras info to fetch. */
-						 "extras", "description,licence",
-						 null);
+		call.set_function("flickr.photos.search");
+		call.add_params("tags", search,
+		                "tag_mode", "all",
+		                "per_page", "10",
+		                "format", "json",
+		                "sort", "relevance",
+		                /* Flickr adds a function around the JSON payload,
+		                   setting 'nojsoncallback' disable that: we get
+		                only plain JSON. */
+		                "nojsoncallback", "1",
+		                // chop off the last comma from the licences string
+		                "license", licenses.substring(0, licenses.length - 1),
+		                /* Extras info to fetch. */
+		                "extras", "description,license",
+		                null);
 		return call;
 	}
 	
-	public override void parse_data(string jsondata) {
-
-		if (jsondata == null) {
-			return;
-		}
+	public override Gtk.Widget? extra_widget()
+	{
+		// create a container
+		var box = new Gtk.HBox(false, 4);
+		
+		// create checkboxes to filter CC licenses
+		share_alike = new Gtk.CheckButton.with_label(_("Share Alike"));
+		for_commercial =
+			new Gtk.CheckButton.with_label(_("For Commercial Use"));
+		
+		// pack them in
+		box.pack_start(share_alike, false, false, 0);
+		box.pack_start(for_commercial, false, false, 0);
+		
+		return box;
+	}
+	
+	public override void parse_data(string jsondata)
+	{
+		if (jsondata == null) return;
 
-		try {
+		try
+		{
 			parser.load_from_data (jsondata);
-		} catch (Error e) {
-			error ("Couldn't parse JSON data: %s", e.message);
+		}
+		catch (Error e)
+		{
+			error("Couldn't parse JSON data: %s", e.message);
 		}
 
-		Json.Object obj = parser.get_root().get_object ();
+		Json.Object obj = parser.get_root().get_object();
 
-		var stat = obj.get_string_member ("stat");
-		if (stat != "ok") {
+		var stat = obj.get_string_member("stat");
+		if (stat != "ok")
+		{
 			warning("The request failed : \nError code: %G\nMessage: %s",
-				    obj.get_int_member ("code"),
-				    obj.get_string_member ("message"));
+			        obj.get_int_member("code"),
+			        obj.get_string_member("message"));
 			return;
 		}
 
-		var photos = obj.get_object_member ("photos");
-		var photo_array = photos.get_array_member ("photo");
+		var photos = obj.get_object_member("photos");
+		var photo_array = photos.get_array_member("photo");
 
 		// TODO : optimization
-		photo_array.foreach_element ( (array, index, element) => 
-			{
-			   iconview_add_thumbnail_from_json (array, index, element);
-			});
-
-
+		photo_array.foreach_element((array, index, element) => {
+			iconview_add_thumbnail_from_json(array, index, element);
+		});
 	}
 	
-	public void iconview_add_thumbnail_from_json (Json.Array array, 
-														uint index,
-														Json.Node element)
+	public void iconview_add_thumbnail_from_json(Json.Array array,
+	                                             uint index,
+	                                             Json.Node element)
 	{
-		Json.Object photo = element.get_object ();
-		int64 farm_int = photo.get_int_member ("farm");
-		
-		string farm = @"$farm_int";
-		string secret = photo.get_string_member ("secret");
-		string server = photo.get_string_member ("server");
-		string id = photo.get_string_member ("id");
-		string http = "http://farm";;
-		string flickr = ".static.flickr.com/";
+		Json.Object photo = element.get_object();
+		int64 farm = photo.get_int_member("farm");
+		var secret = photo.get_string_member("secret");
+		var server = photo.get_string_member("server");
+		var id = photo.get_string_member("id");
 		
 		var image = new FlickrMedia();
-		image.file_link = http + farm + flickr + server + "/" + id + "_" + secret + "_z.jpg";
-		image.thumb_link = http + farm + flickr + server + "/" + id + "_" + secret + "_m.jpg";
+		image.file_link = URL_FORMAT.printf(farm, server, id, secret, "z");
+		image.thumb_link = URL_FORMAT.printf(farm, server, id, secret, "m");
 		// TODO : unittest to track Flickr API changes.
 		// TODO : license
-		image.title = photo.get_string_member ("title");
-		image.description = photo.get_object_member ("description").get_string_member ("_content");
-		image.author = photo.get_string_member ("owner");
+		image.title = photo.get_string_member("title");
+		image.description =
+			photo.get_object_member("description").
+			get_string_member("_content");
+		image.author = photo.get_string_member("owner");
 		
 		add_media(image);
 	}
diff --git a/ease/ease-import-oca-service.vala b/ease/ease-import-oca-service.vala
index b7707f0..279581c 100644
--- a/ease/ease-import-oca-service.vala
+++ b/ease/ease-import-oca-service.vala
@@ -61,8 +61,6 @@ internal class Ease.OCAService : Plugin.ImportService
 				for (Xml.Node* tag = itr->children;
 				     tag != null; tag = tag->next)
 				{
-					debug(tag->name);
-					
 					switch (tag->name)
 					{
 						case "title":
diff --git a/ease/ease-import-widget.vala b/ease/ease-import-widget.vala
index 1bfa355..510afc3 100644
--- a/ease/ease-import-widget.vala
+++ b/ease/ease-import-widget.vala
@@ -1,3 +1,20 @@
+/*  Ease, a GTK presentation application
+    Copyright (C) 2010 Nate Stedman
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
 internal class Ease.ImportWidget : Gtk.Alignment
 {
 	private const string UI_FILE_PATH = "import-widget.ui";
@@ -49,6 +66,11 @@ internal class Ease.ImportWidget : Gtk.Alignment
 	internal Gtk.Widget no_results;
 	
 	/**
+	 * Extra widget for the service.
+	 */
+	internal Gtk.Widget extra_widget;
+	
+	/**
 	 * The ImportService associated with this 
 	 */
 	private Plugin.ImportService service;
@@ -85,6 +107,16 @@ internal class Ease.ImportWidget : Gtk.Alignment
 		}
 		catch (Error e) { error("Error loading UI: %s", e.message); }
 		
+		// bottom alignment and extra widget
+		extra_widget = service.extra_widget();
+		if (extra_widget != null)
+		{
+			
+			extra_widget.show_all();
+			(builder.get_object("extra-alignment") as Gtk.Alignment).
+				add(extra_widget);
+		}
+		
 		// search field
 		search = builder.get_object("search") as Gtk.Entry;
 		search.icon_press.connect(() => search.text = "");



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