[ease/flickr] Adding basic FlickrFetcher.



commit a394be6f61c6a230ff4c0a626000c717c40134ba
Author: Stéphane Maniaci <stephane maniaci gmail com>
Date:   Thu Jun 17 00:39:11 2010 +0200

    Adding basic FlickrFetcher.
    
    This need more love, and I must figure out how to include it in Ease
    (plugins infrastructure comes on stage), and how to alter the build
    process so it builds the plugins as well and stuff.

 plugins/flickr.ui   |  142 +++++++++++++++++++++++++++++++++++++++
 plugins/flickr.vala |  183 +++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 325 insertions(+), 0 deletions(-)
---
diff --git a/plugins/flickr.ui b/plugins/flickr.ui
new file mode 100644
index 0000000..c97821f
--- /dev/null
+++ b/plugins/flickr.ui
@@ -0,0 +1,142 @@
+<?xml version="1.0"?>
+<interface>
+  <requires lib="gtk+" version="2.16"/>
+  <!-- interface-naming-policy project-wide -->
+  <object class="GtkDialog" id="dialog1">
+    <property name="border_width">5</property>
+    <property name="title" translatable="yes">Flickr fetcher</property>
+    <property name="default_width">700</property>
+    <property name="default_height">480</property>
+    <property name="type_hint">normal</property>
+    <property name="has_separator">False</property>
+    <signal name="destroy" handler="gtk_main_quit"/>
+    <signal name="close" handler="gtk_main_quit"/>
+    <signal name="response" handler="flickr_fetcher_on_dialog_response"/>
+    <child internal-child="vbox">
+      <object class="GtkVBox" id="dialog-vbox1">
+        <property name="visible">True</property>
+        <property name="spacing">2</property>
+        <child>
+          <object class="GtkVBox" id="vbox1">
+            <property name="visible">True</property>
+            <child>
+              <object class="GtkHBox" id="hbox1">
+                <property name="visible">True</property>
+                <child>
+                  <object class="GtkEntry" id="searchentry">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="invisible_char">&#x25CF;</property>
+                    <property name="secondary_icon_stock">gtk-find</property>
+                  </object>
+                  <packing>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkButton" id="searchbutton">
+                    <property name="label" translatable="yes">_Search</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="can_default">True</property>
+                    <property name="receives_default">True</property>
+                    <property name="use_underline">True</property>
+                    <signal name="clicked" handler="flickr_fetcher_on_search_button"/>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">False</property>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkScrolledWindow" id="scrolledwindow1">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="hscrollbar_policy">automatic</property>
+                <property name="vscrollbar_policy">automatic</property>
+                <child>
+                  <object class="GtkIconView" id="iconview1">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="border_width">1</property>
+                    <property name="model">liststore1</property>
+                  </object>
+                </child>
+              </object>
+              <packing>
+                <property name="position">1</property>
+              </packing>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+          </object>
+          <packing>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child internal-child="action_area">
+          <object class="GtkHButtonBox" id="dialog-action_area1">
+            <property name="visible">True</property>
+            <property name="layout_style">end</property>
+            <child>
+              <object class="GtkButton" id="cancelbutton">
+                <property name="label" translatable="yes">_Cancel</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_underline">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButton" id="inserbutton">
+                <property name="label" translatable="yes">_Insert</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_underline">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="pack_type">end</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+    <action-widgets>
+      <action-widget response="0">cancelbutton</action-widget>
+      <action-widget response="0">inserbutton</action-widget>
+    </action-widgets>
+  </object>
+  <object class="GtkListStore" id="liststore1">
+    <columns>
+      <!-- column-name id -->
+      <column type="gchararray"/>
+      <!-- column-name title -->
+      <column type="gchararray"/>
+      <!-- column-name preview -->
+      <column type="GdkPixbuf"/>
+    </columns>
+  </object>
+</interface>
diff --git a/plugins/flickr.vala b/plugins/flickr.vala
new file mode 100644
index 0000000..00aa3fd
--- /dev/null
+++ b/plugins/flickr.vala
@@ -0,0 +1,183 @@
+using Rest;
+using Json;
+using Gtk;
+
+public class FlickrFetcher {
+
+	/* Flickr stuff */
+	private const string api_key = "17c40bceda03e0d6f947b001e7c62058";
+	private const string secret = "a7c16179a409418b";
+
+	private Rest.FlickrProxy proxy;
+	// TODO : FlickrProxyCall is broken?
+	private Rest.ProxyCall call;
+
+	/* Json parser */
+	private Json.Parser parser;
+
+	/* UI elements */
+	private Gtk.Dialog dialog;
+	private Gtk.Entry search_entry;
+	private Gtk.Button search_button;
+	private Gtk.IconView iconview;
+	private Gtk.Builder builder;
+
+	private Gtk.ListStore store;
+
+	private Gdk.Pixbuf? gdk_pixbug_from_uri (string uri) {
+
+		File file = File.new_for_uri (uri);
+		FileInputStream filestream;
+		try {
+			filestream = file.read (null);
+		} catch (Error e) {
+			filestream = null;
+			error ("Couldn't read distant file : %s", e.message);
+		}
+		assert (filestream != null);
+		Gdk.Pixbuf pix;
+		try {
+			pix = new Gdk.Pixbuf.from_stream_at_scale (filestream,
+														   200,
+														   200,
+														   true,
+														   null);
+		} catch (Error e) {
+			error ("Couldn't create pixbuf from file: %s", e.message);
+			pix = null;
+		}
+		return pix;
+	}
+
+
+	private string get_flickr_photos_from_tags (string tags) {
+
+		call.set_function ("flickr.photos.search");
+		call.add_params ("tags", tags,
+						 "per_page", "10",
+						 "format", "json",
+						 /* 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,owner_name",
+						 null);
+		// TODO : asyncing
+		try {
+			call.run (null);
+		} catch (Error e) {
+			error ("Could make call: %s\n", e.message);
+		}
+
+		string answer = call.get_payload ();
+		assert (answer != null);
+		return answer;
+	}
+
+	private void parse_flickr_photos (string jsondata) {
+		
+		try {
+			parser.load_from_data (jsondata);
+		} catch (Error e) {
+			error ("Couldn't parse JSON data: %s", e.message);
+		}
+
+		// print ("Payload: %s", jsondata);
+		Json.Object obj = parser.get_root().get_object ();
+		var photos = obj.get_object_member ("photos");
+		var photo_array = photos.get_array_member ("photo");
+
+		// TODO : optimization
+		photo_array.foreach_element ( (array, index, element) =>
+			{
+				Gtk.TreeIter iter;
+				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 stat = ".static.flickr.com/";
+
+				string uri = http + farm + stat + server + "/" + id + "_" + secret + ".jpg";
+				// TODO : unittest to track Flickr's URIs changes.
+
+				var pixbuf = gdk_pixbug_from_uri (uri);
+
+				string title = photo.get_string_member ("title");
+
+				/* Adding to the IconView */
+				store.append (out iter);
+				store.set (iter,
+						   0, id, 
+						   1, title,
+						   2, pixbuf,
+						   -1);
+				// FIXME : window is not updated till the whole function finishes.
+			});
+	}	
+	
+	[CCode (instance_pos = -1)]
+	public void on_search_button (Button? b) {
+		
+		string tags = this.search_entry.get_text ();
+
+		string answer = get_flickr_photos_from_tags (tags);
+		parse_flickr_photos (answer);
+	}
+
+	[CCode (instance_pos = -1)]
+	public void on_dialog_response (Gtk.Dialog dialog, int response) {
+
+		stdout.printf ("In!\n");
+	}
+
+	public FlickrFetcher() {
+
+		proxy = new Rest.FlickrProxy (api_key, secret);
+		call = proxy.new_call ();
+		parser = new Json.Parser ();
+		builder = new Gtk.Builder ();
+
+		try {
+			builder.add_from_file ("flickr.ui");
+		} catch (Error e) {
+			stdout.printf ("Error parsing UI : %s\n", e.message);
+			builder = null;
+		}
+
+		assert (builder != null);
+
+		dialog = builder.get_object ("dialog1") as Gtk.Dialog;
+		iconview = builder.get_object ("iconview1") as Gtk.IconView;
+		search_button = builder.get_object ("searchbutton") as Gtk.Button;
+		search_entry = builder.get_object ("searchentry") as Gtk.Entry;
+		store = builder.get_object ("liststore1") as Gtk.ListStore;
+
+		iconview.set_pixbuf_column (2);
+		iconview.set_text_column (1);
+
+		search_button.grab_default ();
+		search_entry.set_activates_default (true);
+		builder.connect_signals (this);
+	}
+
+	public void run () {
+		dialog.run ();
+	}
+}
+
+
+public static int main (string []args)
+{
+	Gtk.init (ref args);
+
+	var dial = new FlickrFetcher ();
+	dial.run ();
+
+	Gtk.main ();
+	return 0;
+}
\ No newline at end of file



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