[gthumb] Flickr: fixed import of photosets greater then 500



commit 96d90a9d517262a9e7e178624c3322af8cba7ce0
Author: Paolo Bacchilega <paobac src gnome org>
Date:   Sat Sep 10 18:39:55 2011 +0200

    Flickr: fixed import of photosets greater then 500
    
    The method flickr.photosets.getPhotos returns a max of 500 photos, call the method multiple times if the photoset contains
    more then 500 photos.
    
    [bug #648701]

 extensions/flicker/dlg-import-from-flickr.c |    2 -
 extensions/flicker/flickr-connection.c      |    2 +-
 extensions/flicker/flickr-service.c         |  173 +++++++++++++++++++--------
 extensions/flicker/flickr-service.h         |    2 -
 gthumb/dom.c                                |   17 +++
 gthumb/dom.h                                |   48 ++++----
 6 files changed, 167 insertions(+), 77 deletions(-)
---
diff --git a/extensions/flicker/dlg-import-from-flickr.c b/extensions/flicker/dlg-import-from-flickr.c
index 628bdbc..fb6c7e9 100644
--- a/extensions/flicker/dlg-import-from-flickr.c
+++ b/extensions/flicker/dlg-import-from-flickr.c
@@ -407,8 +407,6 @@ photoset_combobox_changed_cb (GtkComboBox *widget,
 	flickr_service_list_photos (data->service,
 				    data->photoset,
 				    "original_format, url_sq, url_t, url_s, url_m, url_o",
-				    0,
-				    0,
 				    data->cancellable,
 				    list_photos_ready_cb,
 				    data);
diff --git a/extensions/flicker/flickr-connection.c b/extensions/flicker/flickr-connection.c
index d3c3d77..d2a5c63 100644
--- a/extensions/flicker/flickr-connection.c
+++ b/extensions/flicker/flickr-connection.c
@@ -215,7 +215,7 @@ flickr_connection_send_message (FlickrConnection    *self,
 	self->priv->cancellable = _g_object_ref (cancellable);
 
 	_g_object_unref (self->priv->result);
-	self->priv->result = g_simple_async_result_new (G_OBJECT (soup_session_cb_data),
+	self->priv->result = g_simple_async_result_new (G_IS_OBJECT (soup_session_cb_data) ? G_OBJECT (soup_session_cb_data) : NULL,
 							callback,
 							user_data,
 							source_tag);
diff --git a/extensions/flicker/flickr-service.c b/extensions/flicker/flickr-service.c
index ae050c5..372d16d 100644
--- a/extensions/flicker/flickr-service.c
+++ b/extensions/flicker/flickr-service.c
@@ -31,6 +31,9 @@
 #include "flickr-user.h"
 
 
+#define IMAGES_PER_PAGE 500
+
+
 typedef struct {
 	FlickrPrivacyType    privacy_level;
 	FlickrSafetyType     safety_level;
@@ -974,16 +977,45 @@ flickr_service_post_photos_finish (FlickrService  *self,
 /* -- flickr_service_list_photos -- */
 
 
+typedef struct {
+	FlickrService       *self;
+	FlickrPhotoset      *photoset;
+	char                *extras;
+	GCancellable        *cancellable;
+	GAsyncReadyCallback  callback;
+	gpointer             user_data;
+	GList               *photos;
+	int                  position;
+} FlickrListPhotosData;
+
+
 static void
-list_photos_ready_cb (SoupSession *session,
-		      SoupMessage *msg,
-		      gpointer     user_data)
+flickr_list_photos_data_free (FlickrListPhotosData *data)
 {
-	FlickrService      *self = user_data;
-	GSimpleAsyncResult *result;
-	SoupBuffer         *body;
-	DomDocument        *doc = NULL;
-	GError             *error = NULL;
+	_g_object_unref (data->self);
+	_g_object_unref (data->photoset);
+	g_free (data->extras);
+	_g_object_unref (data->cancellable);
+	g_free (data);
+}
+
+
+static void
+flickr_service_list_photoset_page (FlickrListPhotosData *data,
+				   int                   page);
+
+
+static void
+flickr_service_list_photoset_paged_ready_cb (SoupSession *session,
+					     SoupMessage *msg,
+					     gpointer     user_data)
+{
+	FlickrListPhotosData *data = user_data;
+	FlickrService        *self = data->self;
+	GSimpleAsyncResult   *result;
+	SoupBuffer           *body;
+	DomDocument          *doc = NULL;
+	GError               *error = NULL;
 
 	result = flickr_connection_get_result (self->priv->conn);
 
@@ -994,6 +1026,7 @@ list_photos_ready_cb (SoupSession *session,
 						 "%s",
 						 soup_status_get_phrase (msg->status_code));
 		g_simple_async_result_complete_in_idle (result);
+		flickr_list_photos_data_free (data);
 		return;
 	}
 
@@ -1001,90 +1034,132 @@ list_photos_ready_cb (SoupSession *session,
 	if (flickr_utils_parse_response (body, &doc, &error)) {
 		DomElement *response;
 		DomElement *node;
-		GList      *photos = NULL;
+		int         pages = 0;
+		int         page = 0;
 
 		response = DOM_ELEMENT (doc)->first_child;
 		for (node = response->first_child; node; node = node->next_sibling) {
 			if (g_strcmp0 (node->tag_name, "photoset") == 0) {
 				DomElement *child;
-				int         position;
 
-				position = 0;
 				for (child = node->first_child; child; child = child->next_sibling) {
 					if (g_strcmp0 (child->tag_name, "photo") == 0) {
 						FlickrPhoto *photo;
 
-						photo = flickr_photo_new ();
+						photo = flickr_photo_new (self->priv->conn->server);
 						dom_domizable_load_from_element (DOM_DOMIZABLE (photo), child);
-						photo->position = position++;
-						photos = g_list_prepend (photos, photo);
+						photo->position = data->position++;
+						data->photos = g_list_prepend (data->photos, photo);
 					}
 				}
+
+				pages = dom_element_get_attribute_as_int (node, "pages");
+				page = dom_element_get_attribute_as_int (node, "page");
 			}
 		}
 
-		photos = g_list_reverse (photos);
-		g_simple_async_result_set_op_res_gpointer (result, photos, (GDestroyNotify) _g_object_list_unref);
+		if (page > pages) {
+			g_simple_async_result_set_error (result,
+							 SOUP_HTTP_ERROR,
+							 0,
+							 "%s",
+							 "Invalid data");
+			g_simple_async_result_complete_in_idle (result);
+			flickr_list_photos_data_free (data);
+		}
+		else if (page < pages) {
+			/* read the next page */
+			flickr_service_list_photoset_page (data, page + 1);
+		}
+		else { /* page == pages */
+			data->photos = g_list_reverse (data->photos);
+			g_simple_async_result_set_op_res_gpointer (result,
+								   _g_object_list_ref (data->photos),
+								   (GDestroyNotify) _g_object_list_unref);
+			g_simple_async_result_complete_in_idle (result);
+			flickr_list_photos_data_free (data);
+		}
 
 		g_object_unref (doc);
 	}
-	else
+	else {
 		g_simple_async_result_set_from_error (result, error);
-
-	g_simple_async_result_complete_in_idle (result);
+		g_simple_async_result_complete_in_idle (result);
+	}
 
 	soup_buffer_free (body);
 }
 
 
-void
-flickr_service_list_photos (FlickrService       *self,
-			    FlickrPhotoset      *photoset,
-			    const char          *extras,
-			    int                  per_page,
-			    int                  page,
-			    GCancellable        *cancellable,
-			    GAsyncReadyCallback  callback,
-			    gpointer             user_data)
+static void
+flickr_service_list_photoset_page (FlickrListPhotosData *data,
+				   int                   n_page)
 {
-	GHashTable  *data_set;
-	char        *s;
-	SoupMessage *msg;
+	FlickrService *self = data->self;
+	GHashTable    *data_set;
+	char          *page = NULL;
+	char          *per_page = NULL;
+	SoupMessage   *msg;
 
-	g_return_if_fail (photoset != NULL);
+	g_return_if_fail (data->photoset != NULL);
 
 	gth_task_progress (GTH_TASK (self->priv->conn), _("Getting the photo list"), NULL, TRUE, 0.0);
 
 	data_set = g_hash_table_new (g_str_hash, g_str_equal);
 	g_hash_table_insert (data_set, "method", "flickr.photosets.getPhotos");
-	g_hash_table_insert (data_set, "photoset_id", photoset->id);
-	if (extras != NULL)
-		g_hash_table_insert (data_set, "extras", (char *) extras);
-	if (per_page > 0) {
-		s = g_strdup_printf ("%d", per_page);
-		g_hash_table_insert (data_set, "per_page", s);
-		g_free (s);
-	}
-	if (page > 0) {
-		s = g_strdup_printf ("%d", page);
-		g_hash_table_insert (data_set, "page", s);
-		g_free (s);
+	g_hash_table_insert (data_set, "photoset_id", data->photoset->id);
+	if (data->extras != NULL)
+		g_hash_table_insert (data_set, "extras", (char *) data->extras);
+
+	if (n_page > 0) {
+		page = g_strdup_printf ("%d", IMAGES_PER_PAGE);
+		g_hash_table_insert (data_set, "per_page", page);
+
+		per_page = g_strdup_printf ("%d", n_page);
+		g_hash_table_insert (data_set, "page", per_page);
 	}
+
 	flickr_connection_add_api_sig (self->priv->conn, data_set);
 	msg = soup_form_request_new_from_hash ("GET", self->priv->conn->server->rest_url, data_set);
 	flickr_connection_send_message (self->priv->conn,
 					msg,
-					cancellable,
-					callback,
-					user_data,
+					data->cancellable,
+					data->callback,
+					data->user_data,
 					flickr_service_list_photos,
-					list_photos_ready_cb,
-					self);
+					flickr_service_list_photoset_paged_ready_cb,
+					data);
 
+	g_free (per_page);
+	g_free (page);
 	g_hash_table_destroy (data_set);
 }
 
 
+void
+flickr_service_list_photos (FlickrService       *self,
+			    FlickrPhotoset      *photoset,
+			    const char          *extras,
+			    GCancellable        *cancellable,
+			    GAsyncReadyCallback  callback,
+			    gpointer             user_data)
+{
+	FlickrListPhotosData *data;
+
+	data = g_new0 (FlickrListPhotosData, 1);
+	data->self = _g_object_ref (self);
+	data->photoset = _g_object_ref (photoset);
+	data->extras = g_strdup (extras);
+	data->cancellable = _g_object_ref (cancellable);
+	data->callback = callback;
+	data->user_data = user_data;
+	data->photos = NULL;
+	data->position = 0;
+
+	flickr_service_list_photoset_page (data, 1);
+}
+
+
 GList *
 flickr_service_list_photos_finish (FlickrService  *self,
 				   GAsyncResult   *result,
diff --git a/extensions/flicker/flickr-service.h b/extensions/flicker/flickr-service.h
index fb20bbe..558c261 100644
--- a/extensions/flicker/flickr-service.h
+++ b/extensions/flicker/flickr-service.h
@@ -112,8 +112,6 @@ GList *           flickr_service_post_photos_finish       (FlickrService
 void              flickr_service_list_photos              (FlickrService        *self,
 							   FlickrPhotoset       *photoset,
 							   const char           *extras,
-							   int                   per_page,
-							   int                   page,
 						           GCancellable         *cancellable,
 						           GAsyncReadyCallback   callback,
 						           gpointer              user_data);
diff --git a/gthumb/dom.c b/gthumb/dom.c
index 60c1c20..0a317a1 100644
--- a/gthumb/dom.c
+++ b/gthumb/dom.c
@@ -20,6 +20,7 @@
  */
 
 #include <config.h>
+#include <stdlib.h>
 #include <string.h>
 #include "dom.h"
 
@@ -310,6 +311,22 @@ dom_element_get_attribute (DomElement *self,
 }
 
 
+int
+dom_element_get_attribute_as_int (DomElement *self,
+				  const char *name)
+{
+	const char *value;
+	int         i;
+
+	i = 0;
+	value = dom_element_get_attribute (self, name);
+	if (value != NULL)
+		i = atoi (value);
+
+	return i;
+}
+
+
 gboolean
 dom_element_has_attribute (DomElement *self,
 			   const char *name)
diff --git a/gthumb/dom.h b/gthumb/dom.h
index 341d054..7294660 100644
--- a/gthumb/dom.h
+++ b/gthumb/dom.h
@@ -18,7 +18,7 @@
  *  You should have received a copy of the GNU General Public License
  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
- 
+
 #ifndef DOM_H
 #define DOM_H
 
@@ -77,7 +77,7 @@ typedef struct _DomDomizableIface DomDomizableIface;
 struct _DomElement {
 	GInitiallyUnowned parent_instance;
 	DomElementPrivate *priv;
-		
+
 	char       *tag_name;
 	char       *prefix;
 	GHashTable *attributes;
@@ -91,15 +91,15 @@ struct _DomElement {
 
 struct _DomElementClass {
 	GInitiallyUnownedClass parent_class;
-	
-	char * (*dump) (DomElement *self, 
+
+	char * (*dump) (DomElement *self,
 			int         level);
 };
 
 struct _DomTextNode {
 	DomElement parent_instance;
 	DomTextNodePrivate *priv;
-	
+
 	char *data;
 };
 
@@ -118,10 +118,10 @@ struct _DomDocumentClass {
 
 struct _DomDomizableIface {
 	GTypeInterface parent_iface;
-	
-	DomElement * (*create_element)    (DomDomizable *self, 
+
+	DomElement * (*create_element)    (DomDomizable *self,
 					   DomDocument  *doc);
-	void         (*load_from_element) (DomDomizable *self, 
+	void         (*load_from_element) (DomDomizable *self,
 					   DomElement   *e);
 };
 
@@ -130,22 +130,24 @@ GQuark        dom_error_quark                       (void);
 /* DomElement */
 
 GType         dom_element_get_type                  (void);
-void          dom_element_append_child              (DomElement   *self, 
+void          dom_element_append_child              (DomElement   *self,
 					             DomElement   *child);
-const char *  dom_element_get_attribute             (DomElement   *self, 
+const char *  dom_element_get_attribute             (DomElement   *self,
 					             const char   *name);
-gboolean      dom_element_has_attribute             (DomElement   *self, 
+int           dom_element_get_attribute_as_int      (DomElement   *self,
+						     const char   *name);
+gboolean      dom_element_has_attribute             (DomElement   *self,
 					             const char   *name);
 gboolean      dom_element_has_child_nodes           (DomElement   *self);
-void          dom_element_remove_attribute          (DomElement   *self, 
+void          dom_element_remove_attribute          (DomElement   *self,
 					             const char   *name);
-DomElement *  dom_element_remove_child              (DomElement   *self, 
+DomElement *  dom_element_remove_child              (DomElement   *self,
 					             DomElement   *node);
-void          dom_element_replace_child             (DomElement   *self, 
-					             DomElement   *new_child, 
+void          dom_element_replace_child             (DomElement   *self,
+					             DomElement   *new_child,
 					             DomElement   *old_child);
-void          dom_element_set_attribute             (DomElement   *self, 
-					             const char   *name, 
+void          dom_element_set_attribute             (DomElement   *self,
+					             const char   *name,
 					             const char   *value);
 const char *  dom_element_get_inner_text            (DomElement   *self);
 
@@ -157,20 +159,20 @@ GType         dom_text_node_get_type                (void);
 
 GType         dom_document_get_type                 (void);
 DomDocument * dom_document_new                      (void);
-DomElement *  dom_document_create_element           (DomDocument  *self, 
+DomElement *  dom_document_create_element           (DomDocument  *self,
 					             const char   *tag_name,
 					             const char   *first_attr,
 					             ...);
-DomElement *  dom_document_create_text_node         (DomDocument  *self, 
+DomElement *  dom_document_create_text_node         (DomDocument  *self,
 					             const char   *data);
 DomElement *  dom_document_create_element_with_text (DomDocument  *self,
-						     const char   *text, 
+						     const char   *text,
 						     const char   *tag_name,
 						     const char   *first_attr,
 						     ...);
 char *        dom_document_dump                     (DomDocument  *self,
 					             gsize        *len);
-gboolean      dom_document_load                     (DomDocument  *self, 
+gboolean      dom_document_load                     (DomDocument  *self,
 					             const char   *xml,
 					             gssize        len,
 					             GError      **error);
@@ -178,9 +180,9 @@ gboolean      dom_document_load                     (DomDocument  *self,
 /* DomDomizable */
 
 GType         dom_domizable_get_type                (void);
-DomElement *  dom_domizable_create_element          (DomDomizable  *self, 
+DomElement *  dom_domizable_create_element          (DomDomizable  *self,
 					             DomDocument   *doc);
-void          dom_domizable_load_from_element       (DomDomizable  *self, 
+void          dom_domizable_load_from_element       (DomDomizable  *self,
 					             DomElement    *e);
 
 G_END_DECLS



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