[gthumb: 3/10] [flicker] unify the authentication code to avoid code duplication



commit bd3f566fc5e123d679dbe2f9c718b75dbc90644b
Author: Paolo Bacchilega <paobac src gnome org>
Date:   Mon Apr 5 18:59:45 2010 +0200

    [flicker] unify the authentication code to avoid code duplication

 extensions/flicker/Makefile.am                     |    2 +
 extensions/flicker/data/ui/export-to-flickr.ui     |    9 +-
 extensions/flicker/dlg-export-to-flickr.c          |  458 +++-------------
 extensions/flicker/dlg-import-from-flickr.c        |  443 +++-------------
 extensions/flicker/flickr-account-manager-dialog.c |    3 +
 extensions/flicker/flickr-authentication.c         |  568 ++++++++++++++++++++
 extensions/flicker/flickr-authentication.h         |   77 +++
 extensions/flicker/flickr-connection.c             |    5 +-
 8 files changed, 790 insertions(+), 775 deletions(-)
---
diff --git a/extensions/flicker/Makefile.am b/extensions/flicker/Makefile.am
index ef79a11..3730c22 100644
--- a/extensions/flicker/Makefile.am
+++ b/extensions/flicker/Makefile.am
@@ -20,6 +20,8 @@ libflicker_la_SOURCES = 			\
 	flickr-account-chooser-dialog.h		\
 	flickr-account-manager-dialog.c		\
 	flickr-account-manager-dialog.h		\
+	flickr-authentication.c			\
+	flickr-authentication.h			\
 	flickr-connection.c			\
 	flickr-connection.h			\
 	flickr-photo.c				\
diff --git a/extensions/flicker/data/ui/export-to-flickr.ui b/extensions/flicker/data/ui/export-to-flickr.ui
index c45d946..21cb7b4 100644
--- a/extensions/flicker/data/ui/export-to-flickr.ui
+++ b/extensions/flicker/data/ui/export-to-flickr.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 -->
@@ -10,20 +10,17 @@
     <child internal-child="vbox">
       <object class="GtkVBox" id="dialog-vbox7">
         <property name="visible">True</property>
-        <property name="orientation">vertical</property>
         <property name="spacing">6</property>
         <child>
           <object class="GtkVBox" id="hbox1">
             <property name="visible">True</property>
             <property name="border_width">5</property>
-            <property name="orientation">vertical</property>
             <property name="spacing">12</property>
             <child>
               <object class="GtkVBox" id="images_box">
                 <property name="width_request">460</property>
-                <property name="height_request">220</property>
+                <property name="height_request">340</property>
                 <property name="visible">True</property>
-                <property name="orientation">vertical</property>
                 <property name="spacing">3</property>
                 <child>
                   <object class="GtkLabel" id="images_info_label">
@@ -43,7 +40,6 @@
             <child>
               <object class="GtkVBox" id="vbox1">
                 <property name="visible">True</property>
-                <property name="orientation">vertical</property>
                 <property name="spacing">6</property>
                 <child>
                   <object class="GtkTable" id="table2">
@@ -74,7 +70,6 @@
                     <child>
                       <object class="GtkVBox" id="vbox4">
                         <property name="visible">True</property>
-                        <property name="orientation">vertical</property>
                         <property name="spacing">3</property>
                         <child>
                           <object class="GtkHBox" id="hbox4">
diff --git a/extensions/flicker/dlg-export-to-flickr.c b/extensions/flicker/dlg-export-to-flickr.c
index 220319a..791dad3 100644
--- a/extensions/flicker/dlg-export-to-flickr.c
+++ b/extensions/flicker/dlg-export-to-flickr.c
@@ -24,8 +24,7 @@
 #include <gtk/gtk.h>
 #include <gthumb.h>
 #include "dlg-export-to-flickr.h"
-#include "flickr-account-chooser-dialog.h"
-#include "flickr-account-manager-dialog.h"
+#include "flickr-authentication.h"
 #include "flickr-photoset.h"
 #include "flickr-service.h"
 #include "flickr-user.h"
@@ -50,21 +49,20 @@ enum {
 
 
 typedef struct {
-	GthBrowser       *browser;
-	GthFileData      *location;
-	GList            *file_list;
-	GtkBuilder       *builder;
-	GtkWidget        *dialog;
-	GtkWidget        *progress_dialog;
-	GList            *accounts;
-	FlickrAccount    *account;
-	FlickrUser       *user;
-	GList            *photosets;
-	FlickrPhotoset   *photoset;
-	FlickrConnection *conn;
-	FlickrService    *service;
-	GList            *photos_ids;
-	GCancellable     *cancellable;
+	GthBrowser           *browser;
+	GthFileData          *location;
+	GList                *file_list;
+	GtkBuilder           *builder;
+	GtkWidget            *dialog;
+	GtkWidget            *progress_dialog;
+	FlickrConnection     *conn;
+	FlickrAuthentication *auth;
+	FlickrService        *service;
+	FlickrUser           *user;
+	GList                *photosets;
+	FlickrPhotoset       *photoset;
+	GList                *photos_ids;
+	GCancellable         *cancellable;
 } DialogData;
 
 
@@ -75,14 +73,13 @@ export_dialog_destroy_cb (GtkWidget  *widget,
 	if (data->conn != NULL)
 		gth_task_completed (GTH_TASK (data->conn), NULL);
 	_g_object_unref (data->cancellable);
+	_g_string_list_free (data->photos_ids);
+	_g_object_unref (data->photoset);
+	_g_object_list_unref (data->photosets);
+	_g_object_unref (data->user);
 	_g_object_unref (data->service);
+	_g_object_unref (data->auth);
 	_g_object_unref (data->conn);
-	_g_object_list_unref (data->accounts);
-	_g_object_unref (data->account);
-	_g_object_unref (data->user);
-	_g_object_list_unref (data->photosets);
-	_g_object_unref (data->photoset);
-	_g_string_list_free (data->photos_ids);
 	_g_object_unref (data->builder);
 	_g_object_list_unref (data->file_list);
 	_g_object_unref (data->location);
@@ -284,7 +281,6 @@ export_dialog_response_cb (GtkDialog *dialog,
 
 	case GTK_RESPONSE_DELETE_EVENT:
 	case GTK_RESPONSE_CANCEL:
-		flickr_accounts_save_to_file (data->accounts, data->account);
 		gtk_widget_destroy (data->dialog);
 		break;
 
@@ -335,19 +331,22 @@ export_dialog_response_cb (GtkDialog *dialog,
 static void
 update_account_list (DialogData *data)
 {
-	GtkTreeIter  iter;
-	int          current_account;
-	int          idx;
-	GList       *scan;
-	char        *free_space;
+	int            current_account_idx;
+	FlickrAccount *current_account;
+	int            idx;
+	GList         *scan;
+	GtkTreeIter    iter;
+	char          *free_space;
 
-	current_account = 0;
 	gtk_list_store_clear (GTK_LIST_STORE (GET_WIDGET ("account_liststore")));
-	for (scan = data->accounts, idx = 0; scan; scan = scan->next, idx++) {
+
+	current_account_idx = 0;
+	current_account = flickr_authentication_get_account (data->auth);
+	for (scan = flickr_authentication_get_accounts (data->auth), idx = 0; scan; scan = scan->next, idx++) {
 		FlickrAccount *account = scan->data;
 
-		if ((data->account != NULL) && (g_strcmp0 (data->account->username, account->username) == 0))
-			current_account = idx;
+		if ((current_account != NULL) && (g_strcmp0 (current_account->username, account->username) == 0))
+			current_account_idx = idx;
 
 		gtk_list_store_append (GTK_LIST_STORE (GET_WIDGET ("account_liststore")), &iter);
 		gtk_list_store_set (GTK_LIST_STORE (GET_WIDGET ("account_liststore")), &iter,
@@ -355,7 +354,7 @@ update_account_list (DialogData *data)
 				    ACCOUNT_NAME_COLUMN, account->username,
 				    -1);
 	}
-	gtk_combo_box_set_active (GTK_COMBO_BOX (GET_WIDGET ("account_combobox")), current_account);
+	gtk_combo_box_set_active (GTK_COMBO_BOX (GET_WIDGET ("account_combobox")), current_account_idx);
 
 	free_space = g_format_size_for_display (data->user->max_bandwidth - data->user->used_bandwidth);
 	gtk_label_set_text (GTK_LABEL (GET_WIDGET ("free_space_label")), free_space);
@@ -364,6 +363,14 @@ update_account_list (DialogData *data)
 
 
 static void
+authentication_accounts_changed_cb (FlickrAuthentication *auth,
+				    gpointer              user_data)
+{
+	update_account_list ((DialogData *) user_data);
+}
+
+
+static void
 photoset_list_ready_cb (GObject      *source_object,
 			GAsyncResult *res,
 			gpointer      user_data)
@@ -412,8 +419,14 @@ photoset_list_ready_cb (GObject      *source_object,
 
 
 static void
-get_photoset_list (DialogData *data)
+authentication_ready_cb (FlickrAuthentication *auth,
+			 FlickrUser           *user,
+			 DialogData           *data)
 {
+	_g_object_unref (data->user);
+	data->user = g_object_ref (user);
+	update_account_list (data);
+
 	flickr_service_list_photosets (data->service,
 				       NULL,
 				       data->cancellable,
@@ -423,349 +436,10 @@ get_photoset_list (DialogData *data)
 
 
 static void
-upload_status_ready_cb (GObject      *source_object,
-			GAsyncResult *res,
-			gpointer      user_data)
-{
-	DialogData *data = user_data;
-	GError     *error = NULL;
-
-	_g_object_unref (data->user);
-	data->user = flickr_service_get_upload_status_finish (FLICKR_SERVICE (source_object), res, &error);
-	if (error != NULL) {
-		if (data->conn != NULL)
-			gth_task_dialog (GTH_TASK (data->conn), TRUE);
-		_gtk_error_dialog_from_gerror_run (GTK_WINDOW (data->browser), _("Could not connect to the server"), &error);
-		gtk_widget_destroy (data->dialog);
-		return;
-	}
-
-	update_account_list (data);
-	get_photoset_list (data);
-}
-
-
-static void
-connect_to_server (DialogData *data)
-{
-	g_return_if_fail (data->account != NULL);
-
-	flickr_connection_set_auth_token (data->conn, data->account->token);
-	if (data->service == NULL)
-		data->service = flickr_service_new (data->conn);
-	flickr_service_get_upload_status (data->service,
-					  data->cancellable,
-					  upload_status_ready_cb,
-					  data);
-}
-
-
-static void
-connection_token_ready_cb (GObject      *source_object,
-			   GAsyncResult *res,
-			   gpointer      user_data)
-{
-	DialogData *data = user_data;
-	GError     *error = NULL;
-	GList      *link;
-
-	if (! flickr_connection_get_token_finish (FLICKR_CONNECTION (source_object), res, &error)) {
-		if (data->conn != NULL)
-			gth_task_dialog (GTH_TASK (data->conn), TRUE);
-		_gtk_error_dialog_from_gerror_run (GTK_WINDOW (data->browser), _("Could not connect to the server"), &error);
-		gtk_widget_destroy (data->dialog);
-		return;
-	}
-
-	_g_object_unref (data->account);
-	data->account = flickr_account_new ();
-	flickr_account_set_username (data->account, flickr_connection_get_username (data->conn));
-	flickr_account_set_token (data->account, flickr_connection_get_auth_token (data->conn));
-
-	link = g_list_find_custom (data->accounts, data->account, (GCompareFunc) flickr_account_cmp);
-	if (link != NULL) {
-		data->accounts = g_list_remove_link (data->accounts, link);
-		_g_object_list_unref (link);
-	}
-	data->accounts = g_list_prepend (data->accounts, g_object_ref (data->account));
-
-	connect_to_server (data);
-}
-
-
-static void
-complete_authorization_messagedialog_response_cb (GtkDialog *dialog,
-						  int        response_id,
-						  gpointer   user_data)
-{
-	DialogData *data = user_data;
-
-	switch (response_id) {
-	case GTK_RESPONSE_HELP:
-		show_help_dialog (GTK_WINDOW (dialog), "flicker-complete-authorization");
-		break;
-
-	case GTK_RESPONSE_DELETE_EVENT:
-	case GTK_RESPONSE_CANCEL:
-		gtk_widget_destroy (GTK_WIDGET (dialog));
-		gtk_widget_destroy (data->dialog);
-		break;
-
-	case GTK_RESPONSE_OK:
-		gtk_widget_destroy (GTK_WIDGET (dialog));
-		gth_task_dialog (GTH_TASK (data->conn), FALSE);
-		flickr_connection_get_token (data->conn,
-					     data->cancellable,
-					     connection_token_ready_cb,
-					     data);
-		break;
-
-	default:
-		break;
-	}
-}
-
-
-static void
-complete_authorization (DialogData *data)
+edit_accounts_button_clicked_cb (GtkButton  *button,
+				 DialogData *data)
 {
-	GtkBuilder *builder;
-	GtkWidget  *dialog;
-
-	gth_task_dialog (GTH_TASK (data->conn), TRUE);
-
-	builder = _gtk_builder_new_from_file ("flicker-complete-authorization.ui", "flicker");
-	dialog = _gtk_builder_get_widget (builder, "complete_authorization_messagedialog");
-	g_object_set_data_full (G_OBJECT (dialog), "builder", builder, g_object_unref);
-	g_signal_connect (dialog,
-			  "response",
-			  G_CALLBACK (complete_authorization_messagedialog_response_cb),
-			  data);
-
-	gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (data->browser));
-	gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
-	gtk_window_present (GTK_WINDOW (dialog));
-}
-
-
-static void
-ask_authorization_messagedialog_response_cb (GtkDialog *dialog,
-					     int        response_id,
-					     gpointer   user_data)
-{
-	DialogData *data = user_data;
-
-	switch (response_id) {
-	case GTK_RESPONSE_HELP:
-		show_help_dialog (GTK_WINDOW (dialog), "flicker-ask-authorization");
-		break;
-
-	case GTK_RESPONSE_DELETE_EVENT:
-	case GTK_RESPONSE_CANCEL:
-		gtk_widget_destroy (GTK_WIDGET (dialog));
-		gtk_widget_destroy (data->dialog);
-		break;
-
-	case GTK_RESPONSE_OK:
-		{
-			char   *url;
-			GError *error = NULL;
-
-			gtk_widget_destroy (GTK_WIDGET (dialog));
-
-			url = flickr_connection_get_login_link (data->conn, FLICKR_ACCESS_WRITE);
-			if (gtk_show_uri (gtk_widget_get_screen (GTK_WIDGET (dialog)), url, 0, &error)) {
-				complete_authorization (data);
-			}
-			else {
-				if (data->conn != NULL)
-					gth_task_dialog (GTH_TASK (data->conn), TRUE);
-				_gtk_error_dialog_from_gerror_run (GTK_WINDOW (data->browser), _("Could not connect to the server"), &error);
-				gtk_widget_destroy (data->dialog);
-			}
-
-			g_free (url);
-		}
-		break;
-
-	default:
-		break;
-	}
-}
-
-
-static void
-ask_authorization (DialogData *data)
-{
-	GtkBuilder *builder;
-	GtkWidget  *dialog;
-
-	gth_task_dialog (GTH_TASK (data->conn), TRUE);
-
-	builder = _gtk_builder_new_from_file ("flicker-ask-authorization.ui", "flicker");
-	dialog = _gtk_builder_get_widget (builder, "ask_authorization_messagedialog");
-	g_object_set_data_full (G_OBJECT (dialog), "builder", builder, g_object_unref);
-	g_signal_connect (dialog,
-			  "response",
-			  G_CALLBACK (ask_authorization_messagedialog_response_cb),
-			  data);
-
-	gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (data->browser));
-	gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
-	gtk_window_present (GTK_WINDOW (dialog));
-}
-
-
-static void
-connection_frob_ready_cb (GObject      *source_object,
-			  GAsyncResult *res,
-			  gpointer      user_data)
-{
-	DialogData *data = user_data;
-	GError     *error = NULL;
-
-	if (! flickr_connection_get_frob_finish (FLICKR_CONNECTION (source_object), res, &error)) {
-		if (data->conn != NULL)
-			gth_task_dialog (GTH_TASK (data->conn), TRUE);
-		_gtk_error_dialog_from_gerror_run (GTK_WINDOW (data->browser), _("Could not connect to the server"), &error);
-		gtk_widget_destroy (data->dialog);
-		return;
-	}
-
-	ask_authorization (data);
-}
-
-
-static void
-start_authorization_process (DialogData *data)
-{
-	flickr_connection_get_frob (data->conn,
-				    data->cancellable,
-				    connection_frob_ready_cb,
-				    data);
-}
-
-
-static void
-account_chooser_dialog_response_cb (GtkDialog *dialog,
-				    int        response_id,
-				    gpointer   user_data)
-{
-	DialogData *data = user_data;
-
-	switch (response_id) {
-	case GTK_RESPONSE_DELETE_EVENT:
-	case GTK_RESPONSE_CANCEL:
-		gtk_widget_destroy (GTK_WIDGET (dialog));
-		gtk_widget_destroy (data->dialog);
-		break;
-
-	case GTK_RESPONSE_OK:
-		_g_object_unref (data->account);
-		data->account = flickr_account_chooser_dialog_get_active (FLICKR_ACCOUNT_CHOOSER_DIALOG (dialog));
-		if (data->account != NULL) {
-			gtk_widget_destroy (GTK_WIDGET (dialog));
-			connect_to_server (data);
-		}
-
-		break;
-
-	case FLICKR_ACCOUNT_CHOOSER_RESPONSE_NEW:
-		gtk_widget_destroy (GTK_WIDGET (dialog));
-		start_authorization_process (data);
-		break;
-
-	default:
-		break;
-	}
-}
-
-
-static void
-auto_select_account (DialogData *data)
-{
-	gtk_widget_hide (data->dialog);
-	gth_task_dialog (GTH_TASK (data->conn), FALSE);
-
-	if (data->accounts != NULL) {
-		if (data->account != NULL) {
-			connect_to_server (data);
-		}
-		else if (data->accounts->next == NULL) {
-			data->account = g_object_ref (data->accounts->data);
-			connect_to_server (data);
-		}
-		else {
-			GtkWidget *dialog;
-
-			gth_task_dialog (GTH_TASK (data->conn), TRUE);
-			dialog = flickr_account_chooser_dialog_new (data->accounts, data->account);
-			g_signal_connect (dialog,
-					  "response",
-					  G_CALLBACK (account_chooser_dialog_response_cb),
-					  data);
-
-			gtk_window_set_title (GTK_WINDOW (dialog), _("Choose Account"));
-			gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (data->browser));
-			gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
-			gtk_window_present (GTK_WINDOW (dialog));
-		}
-	}
-	else
-		start_authorization_process (data);
-}
-
-
-static void
-account_manager_dialog_response_cb (GtkDialog *dialog,
-			            int        response_id,
-			            gpointer   user_data)
-{
-	DialogData *data = user_data;
-
-	switch (response_id) {
-	case GTK_RESPONSE_DELETE_EVENT:
-	case GTK_RESPONSE_CANCEL:
-		gtk_widget_destroy (GTK_WIDGET (dialog));
-		break;
-
-	case GTK_RESPONSE_OK:
-		_g_object_list_unref (data->accounts);
-		data->accounts = flickr_account_manager_dialog_get_accounts (FLICKR_ACCOUNT_MANAGER_DIALOG (dialog));
-		if (! g_list_find_custom (data->accounts, data->account, (GCompareFunc) flickr_account_cmp)) {
-			_g_object_unref (data->account);
-			data->account = NULL;
-			auto_select_account (data);
-		}
-		else
-			update_account_list (data);
-		flickr_accounts_save_to_file (data->accounts, data->account);
-		gtk_widget_destroy (GTK_WIDGET (dialog));
-		break;
-
-	default:
-		break;
-	}
-}
-
-
-static void
-edit_accounts_button_clicked_cb (GtkButton *button,
-			         gpointer   user_data)
-{
-	DialogData *data = user_data;
-	GtkWidget  *dialog;
-
-	dialog = flickr_account_manager_dialog_new (data->accounts);
-	g_signal_connect (dialog,
-			  "response",
-			  G_CALLBACK (account_manager_dialog_response_cb),
-			  data);
-
-	gtk_window_set_title (GTK_WINDOW (dialog), _("Edit Accounts"));
-	gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (data->dialog));
-	gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
-	gtk_window_present (GTK_WINDOW (dialog));
+	flickr_authentication_edit_accounts (data->auth, GTK_WINDOW (data->dialog));
 }
 
 
@@ -785,13 +459,10 @@ account_combobox_changed_cb (GtkComboBox *widget,
 			    ACCOUNT_DATA_COLUMN, &account,
 			    -1);
 
-	if (flickr_account_cmp (account, data->account) != 0) {
-		_g_object_unref (data->account);
-		data->account = account;
-		auto_select_account (data);
-	}
-	else
-		g_object_unref (account);
+	if (flickr_account_cmp (account, flickr_authentication_get_account (data->auth)) != 0)
+		flickr_authentication_connect (data->auth, account);
+
+	g_object_unref (account);
 }
 
 
@@ -885,10 +556,23 @@ dlg_export_to_flickr (GthBrowser *browser,
 			  data);
 
 	data->conn = flickr_connection_new ();
+	data->service = flickr_service_new (data->conn);
+	data->auth = flickr_authentication_new (data->conn,
+						data->service,
+						data->cancellable,
+						GTK_WIDGET (data->browser),
+						data->dialog);
+	g_signal_connect (data->auth,
+			  "ready",
+			  G_CALLBACK (authentication_ready_cb),
+			  data);
+	g_signal_connect (data->auth,
+			  "accounts_changed",
+			  G_CALLBACK (authentication_accounts_changed_cb),
+			  data);
+
 	data->progress_dialog = gth_progress_dialog_new (GTK_WINDOW (data->browser));
 	gth_progress_dialog_add_task (GTH_PROGRESS_DIALOG (data->progress_dialog), GTH_TASK (data->conn));
 
-	data->accounts = flickr_accounts_load_from_file ();
-	data->account = flickr_accounts_find_default (data->accounts);
-	auto_select_account (data);
+	flickr_authentication_auto_connect (data->auth);
 }
diff --git a/extensions/flicker/dlg-import-from-flickr.c b/extensions/flicker/dlg-import-from-flickr.c
index 9fdd4a8..27e2a7d 100644
--- a/extensions/flicker/dlg-import-from-flickr.c
+++ b/extensions/flicker/dlg-import-from-flickr.c
@@ -26,9 +26,7 @@
 #include <gthumb.h>
 #include <extensions/importer/importer.h>
 #include "dlg-import-from-flickr.h"
-#include "flickr-account.h"
-#include "flickr-account-chooser-dialog.h"
-#include "flickr-account-manager-dialog.h"
+#include "flickr-authentication.h"
 #include "flickr-photo.h"
 #include "flickr-photoset.h"
 #include "flickr-service.h"
@@ -55,22 +53,21 @@ enum {
 
 
 typedef struct {
-	GthBrowser       *browser;
-	GthFileData      *location;
-	GtkBuilder       *builder;
-	GtkWidget        *dialog;
-	GtkWidget        *preferences_dialog;
-	GtkWidget        *progress_dialog;
-	GtkWidget        *file_list;
-	GList            *accounts;
-	FlickrAccount    *account;
-	FlickrUser       *user;
-	GList            *photosets;
-	FlickrPhotoset   *photoset;
-	GList            *photos;
-	FlickrConnection *conn;
-	FlickrService    *service;
-	GCancellable     *cancellable;
+	GthBrowser           *browser;
+	GthFileData          *location;
+	GtkBuilder           *builder;
+	GtkWidget            *dialog;
+	GtkWidget            *preferences_dialog;
+	GtkWidget            *progress_dialog;
+	FlickrConnection     *conn;
+	FlickrAuthentication *auth;
+	FlickrService        *service;
+	GtkWidget            *file_list;
+	FlickrUser           *user;
+	GList                *photosets;
+	FlickrPhotoset       *photoset;
+	GList                *photos;
+	GCancellable         *cancellable;
 } DialogData;
 
 
@@ -81,10 +78,9 @@ import_dialog_destroy_cb (GtkWidget  *widget,
 	if (data->conn != NULL)
 		gth_task_completed (GTH_TASK (data->conn), NULL);
 	_g_object_unref (data->cancellable);
-	_g_object_unref (data->service);
 	_g_object_unref (data->conn);
-	_g_object_list_unref (data->accounts);
-	_g_object_unref (data->account);
+	_g_object_unref (data->service);
+	_g_object_unref (data->auth);
 	_g_object_unref (data->user);
 	_g_object_list_unref (data->photosets);
 	_g_object_unref (data->photoset);
@@ -129,7 +125,6 @@ import_dialog_response_cb (GtkDialog *dialog,
 
 	case GTK_RESPONSE_DELETE_EVENT:
 	case GTK_RESPONSE_CANCEL:
-		flickr_accounts_save_to_file (data->accounts, data->account);
 		gtk_widget_destroy (data->dialog);
 		break;
 
@@ -200,18 +195,21 @@ import_dialog_response_cb (GtkDialog *dialog,
 static void
 update_account_list (DialogData *data)
 {
-	GtkTreeIter  iter;
-	int          current_account;
-	int          idx;
-	GList       *scan;
+	int            current_account_idx;
+	FlickrAccount *current_account;
+	int            idx;
+	GList         *scan;
+	GtkTreeIter    iter;
 
-	current_account = 0;
 	gtk_list_store_clear (GTK_LIST_STORE (GET_WIDGET ("account_liststore")));
-	for (scan = data->accounts, idx = 0; scan; scan = scan->next, idx++) {
+
+	current_account_idx = 0;
+	current_account = flickr_authentication_get_account (data->auth);
+	for (scan = flickr_authentication_get_accounts (data->auth), idx = 0; scan; scan = scan->next, idx++) {
 		FlickrAccount *account = scan->data;
 
-		if ((data->account != NULL) && (g_strcmp0 (data->account->username, account->username) == 0))
-			current_account = idx;
+		if ((current_account != NULL) && (g_strcmp0 (current_account->username, account->username) == 0))
+			current_account_idx = idx;
 
 		gtk_list_store_append (GTK_LIST_STORE (GET_WIDGET ("account_liststore")), &iter);
 		gtk_list_store_set (GTK_LIST_STORE (GET_WIDGET ("account_liststore")), &iter,
@@ -219,7 +217,7 @@ update_account_list (DialogData *data)
 				    ACCOUNT_NAME_COLUMN, account->username,
 				    -1);
 	}
-	gtk_combo_box_set_active (GTK_COMBO_BOX (GET_WIDGET ("account_combobox")), current_account);
+	gtk_combo_box_set_active (GTK_COMBO_BOX (GET_WIDGET ("account_combobox")), current_account_idx);
 }
 
 
@@ -270,8 +268,14 @@ photoset_list_ready_cb (GObject      *source_object,
 
 
 static void
-get_photoset_list (DialogData *data)
+authentication_ready_cb (FlickrAuthentication *auth,
+			 FlickrUser           *user,
+			 DialogData           *data)
 {
+	_g_object_unref (data->user);
+	data->user = g_object_ref (user);
+	update_account_list (data);
+
 	flickr_service_list_photosets (data->service,
 				       NULL,
 				       data->cancellable,
@@ -281,349 +285,18 @@ get_photoset_list (DialogData *data)
 
 
 static void
-upload_status_ready_cb (GObject      *source_object,
-			GAsyncResult *res,
-			gpointer      user_data)
+authentication_accounts_changed_cb (FlickrAuthentication *auth,
+				    gpointer              user_data)
 {
-	DialogData *data = user_data;
-	GError     *error = NULL;
-
-	_g_object_unref (data->user);
-	data->user = flickr_service_get_upload_status_finish (FLICKR_SERVICE (source_object), res, &error);
-	if (error != NULL) {
-		if (data->conn != NULL)
-			gth_task_dialog (GTH_TASK (data->conn), TRUE);
-		_gtk_error_dialog_from_gerror_run (GTK_WINDOW (data->browser), _("Could not connect to the server"), &error);
-		gtk_widget_destroy (data->dialog);
-		return;
-	}
-
-	update_account_list (data);
-	get_photoset_list (data);
+	update_account_list ((DialogData *) user_data);
 }
 
 
 static void
-connect_to_server (DialogData *data)
+edit_accounts_button_clicked_cb (GtkButton  *button,
+				 DialogData *data)
 {
-	g_return_if_fail (data->account != NULL);
-
-	flickr_connection_set_auth_token (data->conn, data->account->token);
-	if (data->service == NULL)
-		data->service = flickr_service_new (data->conn);
-	flickr_service_get_upload_status (data->service,
-					  data->cancellable,
-					  upload_status_ready_cb,
-					  data);
-}
-
-
-static void
-connection_token_ready_cb (GObject      *source_object,
-			   GAsyncResult *res,
-			   gpointer      user_data)
-{
-	DialogData *data = user_data;
-	GError     *error = NULL;
-	GList      *link;
-
-	if (! flickr_connection_get_token_finish (FLICKR_CONNECTION (source_object), res, &error)) {
-		if (data->conn != NULL)
-			gth_task_dialog (GTH_TASK (data->conn), TRUE);
-		_gtk_error_dialog_from_gerror_run (GTK_WINDOW (data->browser), _("Could not connect to the server"), &error);
-		gtk_widget_destroy (data->dialog);
-		return;
-	}
-
-	_g_object_unref (data->account);
-	data->account = flickr_account_new ();
-	flickr_account_set_username (data->account, flickr_connection_get_username (data->conn));
-	flickr_account_set_token (data->account, flickr_connection_get_auth_token (data->conn));
-
-	link = g_list_find_custom (data->accounts, data->account, (GCompareFunc) flickr_account_cmp);
-	if (link != NULL) {
-		data->accounts = g_list_remove_link (data->accounts, link);
-		_g_object_list_unref (link);
-	}
-	data->accounts = g_list_prepend (data->accounts, g_object_ref (data->account));
-
-	connect_to_server (data);
-}
-
-
-static void
-complete_authorization_messagedialog_response_cb (GtkDialog *dialog,
-						  int        response_id,
-						  gpointer   user_data)
-{
-	DialogData *data = user_data;
-
-	switch (response_id) {
-	case GTK_RESPONSE_HELP:
-		show_help_dialog (GTK_WINDOW (dialog), "flicker-complete-authorization");
-		break;
-
-	case GTK_RESPONSE_DELETE_EVENT:
-	case GTK_RESPONSE_CANCEL:
-		gtk_widget_destroy (GTK_WIDGET (dialog));
-		gtk_widget_destroy (data->dialog);
-		break;
-
-	case GTK_RESPONSE_OK:
-		gtk_widget_destroy (GTK_WIDGET (dialog));
-		gth_task_dialog (GTH_TASK (data->conn), FALSE);
-		flickr_connection_get_token (data->conn,
-					     data->cancellable,
-					     connection_token_ready_cb,
-					     data);
-		break;
-
-	default:
-		break;
-	}
-}
-
-
-static void
-complete_authorization (DialogData *data)
-{
-	GtkBuilder *builder;
-	GtkWidget  *dialog;
-
-	gth_task_dialog (GTH_TASK (data->conn), TRUE);
-
-	builder = _gtk_builder_new_from_file ("flicker-complete-authorization.ui", "flicker");
-	dialog = _gtk_builder_get_widget (builder, "complete_authorization_messagedialog");
-	g_object_set_data_full (G_OBJECT (dialog), "builder", builder, g_object_unref);
-	g_signal_connect (dialog,
-			  "response",
-			  G_CALLBACK (complete_authorization_messagedialog_response_cb),
-			  data);
-
-	gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (data->browser));
-	gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
-	gtk_window_present (GTK_WINDOW (dialog));
-}
-
-
-static void
-ask_authorization_messagedialog_response_cb (GtkDialog *dialog,
-					     int        response_id,
-					     gpointer   user_data)
-{
-	DialogData *data = user_data;
-
-	switch (response_id) {
-	case GTK_RESPONSE_HELP:
-		show_help_dialog (GTK_WINDOW (dialog), "flicker-ask-authorization");
-		break;
-
-	case GTK_RESPONSE_DELETE_EVENT:
-	case GTK_RESPONSE_CANCEL:
-		gtk_widget_destroy (GTK_WIDGET (dialog));
-		gtk_widget_destroy (data->dialog);
-		break;
-
-	case GTK_RESPONSE_OK:
-		{
-			char   *url;
-			GError *error = NULL;
-
-			gtk_widget_destroy (GTK_WIDGET (dialog));
-
-			url = flickr_connection_get_login_link (data->conn, FLICKR_ACCESS_WRITE);
-			if (gtk_show_uri (gtk_widget_get_screen (GTK_WIDGET (dialog)), url, 0, &error)) {
-				complete_authorization (data);
-			}
-			else {
-				if (data->conn != NULL)
-					gth_task_dialog (GTH_TASK (data->conn), TRUE);
-				_gtk_error_dialog_from_gerror_run (GTK_WINDOW (data->browser), _("Could not connect to the server"), &error);
-				gtk_widget_destroy (data->dialog);
-			}
-
-			g_free (url);
-		}
-		break;
-
-	default:
-		break;
-	}
-}
-
-
-static void
-ask_authorization (DialogData *data)
-{
-	GtkBuilder *builder;
-	GtkWidget  *dialog;
-
-	gth_task_dialog (GTH_TASK (data->conn), TRUE);
-
-	builder = _gtk_builder_new_from_file ("flicker-ask-authorization.ui", "flicker");
-	dialog = _gtk_builder_get_widget (builder, "ask_authorization_messagedialog");
-	g_object_set_data_full (G_OBJECT (dialog), "builder", builder, g_object_unref);
-	g_signal_connect (dialog,
-			  "response",
-			  G_CALLBACK (ask_authorization_messagedialog_response_cb),
-			  data);
-
-	gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (data->browser));
-	gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
-	gtk_window_present (GTK_WINDOW (dialog));
-}
-
-
-static void
-connection_frob_ready_cb (GObject      *source_object,
-			  GAsyncResult *res,
-			  gpointer      user_data)
-{
-	DialogData *data = user_data;
-	GError     *error = NULL;
-
-	if (! flickr_connection_get_frob_finish (FLICKR_CONNECTION (source_object), res, &error)) {
-		if (data->conn != NULL)
-			gth_task_dialog (GTH_TASK (data->conn), TRUE);
-		_gtk_error_dialog_from_gerror_run (GTK_WINDOW (data->browser), _("Could not connect to the server"), &error);
-		gtk_widget_destroy (data->dialog);
-		return;
-	}
-
-	ask_authorization (data);
-}
-
-
-static void
-start_authorization_process (DialogData *data)
-{
-	flickr_connection_get_frob (data->conn,
-				    data->cancellable,
-				    connection_frob_ready_cb,
-				    data);
-}
-
-
-static void
-account_chooser_dialog_response_cb (GtkDialog *dialog,
-				    int        response_id,
-				    gpointer   user_data)
-{
-	DialogData *data = user_data;
-
-	switch (response_id) {
-	case GTK_RESPONSE_DELETE_EVENT:
-	case GTK_RESPONSE_CANCEL:
-		gtk_widget_destroy (GTK_WIDGET (dialog));
-		gtk_widget_destroy (data->dialog);
-		break;
-
-	case GTK_RESPONSE_OK:
-		_g_object_unref (data->account);
-		data->account = flickr_account_chooser_dialog_get_active (FLICKR_ACCOUNT_CHOOSER_DIALOG (dialog));
-		if (data->account != NULL) {
-			gtk_widget_destroy (GTK_WIDGET (dialog));
-			connect_to_server (data);
-		}
-
-		break;
-
-	case FLICKR_ACCOUNT_CHOOSER_RESPONSE_NEW:
-		gtk_widget_destroy (GTK_WIDGET (dialog));
-		start_authorization_process (data);
-		break;
-
-	default:
-		break;
-	}
-}
-
-
-static void
-auto_select_account (DialogData *data)
-{
-	gtk_widget_hide (data->dialog);
-	gth_task_dialog (GTH_TASK (data->conn), FALSE);
-
-	if (data->accounts != NULL) {
-		if (data->account != NULL) {
-			connect_to_server (data);
-		}
-		else if (data->accounts->next == NULL) {
-			data->account = g_object_ref (data->accounts->data);
-			connect_to_server (data);
-		}
-		else {
-			GtkWidget *dialog;
-
-			gth_task_dialog (GTH_TASK (data->conn), TRUE);
-			dialog = flickr_account_chooser_dialog_new (data->accounts, data->account);
-			g_signal_connect (dialog,
-					  "response",
-					  G_CALLBACK (account_chooser_dialog_response_cb),
-					  data);
-
-			gtk_window_set_title (GTK_WINDOW (dialog), _("Choose Account"));
-			gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (data->browser));
-			gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
-			gtk_window_present (GTK_WINDOW (dialog));
-		}
-	}
-	else
-		start_authorization_process (data);
-}
-
-
-static void
-account_manager_dialog_response_cb (GtkDialog *dialog,
-			            int        response_id,
-			            gpointer   user_data)
-{
-	DialogData *data = user_data;
-
-	switch (response_id) {
-	case GTK_RESPONSE_DELETE_EVENT:
-	case GTK_RESPONSE_CANCEL:
-		gtk_widget_destroy (GTK_WIDGET (dialog));
-		break;
-
-	case GTK_RESPONSE_OK:
-		_g_object_list_unref (data->accounts);
-		data->accounts = flickr_account_manager_dialog_get_accounts (FLICKR_ACCOUNT_MANAGER_DIALOG (dialog));
-		if (! g_list_find_custom (data->accounts, data->account, (GCompareFunc) flickr_account_cmp)) {
-			_g_object_unref (data->account);
-			data->account = NULL;
-			auto_select_account (data);
-		}
-		else
-			update_account_list (data);
-		flickr_accounts_save_to_file (data->accounts, data->account);
-		gtk_widget_destroy (GTK_WIDGET (dialog));
-		break;
-
-	default:
-		break;
-	}
-}
-
-
-static void
-edit_accounts_button_clicked_cb (GtkButton *button,
-			         gpointer   user_data)
-{
-	DialogData *data = user_data;
-	GtkWidget  *dialog;
-
-	dialog = flickr_account_manager_dialog_new (data->accounts);
-	g_signal_connect (dialog,
-			  "response",
-			  G_CALLBACK (account_manager_dialog_response_cb),
-			  data);
-
-	gtk_window_set_title (GTK_WINDOW (dialog), _("Edit Accounts"));
-	gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (data->dialog));
-	gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
-	gtk_window_present (GTK_WINDOW (dialog));
+	flickr_authentication_edit_accounts (data->auth, GTK_WINDOW (data->dialog));
 }
 
 
@@ -643,13 +316,10 @@ account_combobox_changed_cb (GtkComboBox *widget,
 			    ACCOUNT_DATA_COLUMN, &account,
 			    -1);
 
-	if (flickr_account_cmp (account, data->account) != 0) {
-		_g_object_unref (data->account);
-		data->account = account;
-		auto_select_account (data);
-	}
-	else
-		g_object_unref (account);
+	if (flickr_account_cmp (account, flickr_authentication_get_account (data->auth)) != 0)
+		flickr_authentication_connect (data->auth, account);
+
+	g_object_unref (account);
 }
 
 
@@ -932,10 +602,23 @@ dlg_import_from_flickr (GthBrowser *browser)
 	update_selection_status (data);
 
 	data->conn = flickr_connection_new ();
+	data->service = flickr_service_new (data->conn);
+	data->auth = flickr_authentication_new (data->conn,
+						data->service,
+						data->cancellable,
+						GTK_WIDGET (data->browser),
+						data->dialog);
+	g_signal_connect (data->auth,
+			  "ready",
+			  G_CALLBACK (authentication_ready_cb),
+			  data);
+	g_signal_connect (data->auth,
+			  "accounts_changed",
+			  G_CALLBACK (authentication_accounts_changed_cb),
+			  data);
+
 	data->progress_dialog = gth_progress_dialog_new (GTK_WINDOW (data->browser));
 	gth_progress_dialog_add_task (GTH_PROGRESS_DIALOG (data->progress_dialog), GTH_TASK (data->conn));
 
-	data->accounts = flickr_accounts_load_from_file ();
-	data->account = flickr_accounts_find_default (data->accounts);
-	auto_select_account (data);
+	flickr_authentication_auto_connect (data->auth);
 }
diff --git a/extensions/flicker/flickr-account-manager-dialog.c b/extensions/flicker/flickr-account-manager-dialog.c
index 6b14f96..63e810a 100644
--- a/extensions/flicker/flickr-account-manager-dialog.c
+++ b/extensions/flicker/flickr-account-manager-dialog.c
@@ -140,6 +140,9 @@ flickr_account_manager_dialog_init (FlickrAccountManagerDialog *self)
 	gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (self))), content, TRUE, TRUE, 0);
 
 	gtk_dialog_add_button (GTK_DIALOG (self),
+			       GTK_STOCK_NEW,
+			       FLICKR_ACCOUNT_MANAGER_RESPONSE_NEW);
+	gtk_dialog_add_button (GTK_DIALOG (self),
 			       GTK_STOCK_CANCEL,
 			       GTK_RESPONSE_CANCEL);
 	gtk_dialog_add_button (GTK_DIALOG (self),
diff --git a/extensions/flicker/flickr-authentication.c b/extensions/flicker/flickr-authentication.c
new file mode 100644
index 0000000..b85640f
--- /dev/null
+++ b/extensions/flicker/flickr-authentication.c
@@ -0,0 +1,568 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ *  GThumb
+ *
+ *  Copyright (C) 2010 Free Software Foundation, Inc.
+ *
+ *  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 2 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, write to the Free Software
+ *  Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include <glib.h>
+#include "flickr-account-chooser-dialog.h"
+#include "flickr-account-manager-dialog.h"
+#include "flickr-authentication.h"
+#include "flickr-user.h"
+#include "flickr-service.h"
+
+
+/* Signals */
+enum {
+	READY,
+	ACCOUNTS_CHANGED,
+	LAST_SIGNAL
+};
+
+struct _FlickrAuthenticationPrivate
+{
+	FlickrConnection *conn;
+	FlickrService    *service;
+	GCancellable     *cancellable;
+	GList            *accounts;
+	FlickrAccount    *account;
+	GtkWidget        *browser;
+	GtkWidget        *dialog;
+};
+
+
+static GObjectClass *parent_class = NULL;
+static guint flickr_authentication_signals[LAST_SIGNAL] = { 0 };
+
+
+GQuark
+flickr_authentication_error_quark (void)
+{
+	return g_quark_from_static_string ("gth-task-error-quark");
+}
+
+
+static void
+flickr_authentication_finalize (GObject *object)
+{
+	FlickrAuthentication *self;
+
+	self = FLICKR_AUTHENTICATION (object);
+	_g_object_unref (self->priv->conn);
+	_g_object_unref (self->priv->service);
+	_g_object_unref (self->priv->cancellable);
+	_g_object_list_unref (self->priv->accounts);
+	_g_object_unref (self->priv->account);
+
+	G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+
+static void
+flickr_authentication_class_init (FlickrAuthenticationClass *class)
+{
+	GObjectClass *object_class;
+
+	parent_class = g_type_class_peek_parent (class);
+	g_type_class_add_private (class, sizeof (FlickrAuthenticationPrivate));
+
+	object_class = (GObjectClass*) class;
+	object_class->finalize = flickr_authentication_finalize;
+
+	/* signals */
+
+	flickr_authentication_signals[READY] =
+		g_signal_new ("ready",
+			      G_TYPE_FROM_CLASS (class),
+			      G_SIGNAL_RUN_LAST,
+			      G_STRUCT_OFFSET (FlickrAuthenticationClass, ready),
+			      NULL, NULL,
+			      g_cclosure_marshal_VOID__OBJECT,
+			      G_TYPE_NONE,
+			      1,
+			      G_TYPE_OBJECT);
+	flickr_authentication_signals[ACCOUNTS_CHANGED] =
+		g_signal_new ("accounts_changed",
+			      G_TYPE_FROM_CLASS (class),
+			      G_SIGNAL_RUN_LAST,
+			      G_STRUCT_OFFSET (FlickrAuthenticationClass, accounts_changed),
+			      NULL, NULL,
+			      g_cclosure_marshal_VOID__VOID,
+			      G_TYPE_NONE,
+			      0);
+}
+
+
+static void
+flickr_authentication_init (FlickrAuthentication *self)
+{
+	self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, FLICKR_TYPE_AUTHENTICATION, FlickrAuthenticationPrivate);
+	self->priv->conn = NULL;
+	self->priv->accounts = NULL;
+	self->priv->account = NULL;
+}
+
+
+GType
+flickr_authentication_get_type (void)
+{
+	static GType type = 0;
+
+	if (! type) {
+		GTypeInfo type_info = {
+			sizeof (GthTaskClass),
+			NULL,
+			NULL,
+			(GClassInitFunc) flickr_authentication_class_init,
+			NULL,
+			NULL,
+			sizeof (GthTask),
+			0,
+			(GInstanceInitFunc) flickr_authentication_init
+		};
+
+		type = g_type_register_static (G_TYPE_OBJECT,
+					       "FlickrAuthentication",
+					       &type_info,
+					       0);
+	}
+
+	return type;
+}
+
+
+FlickrAuthentication *
+flickr_authentication_new (FlickrConnection *conn,
+			   FlickrService    *service,
+			   GCancellable     *cancellable,
+			   GtkWidget        *browser,
+			   GtkWidget        *dialog)
+{
+	FlickrAuthentication *self;
+
+	g_return_val_if_fail (conn != NULL, NULL);
+
+	self = (FlickrAuthentication *) g_object_new (FLICKR_TYPE_AUTHENTICATION, NULL);
+	self->priv->conn = g_object_ref (conn);
+	self->priv->service = g_object_ref (service);
+	self->priv->cancellable = _g_object_ref (cancellable);
+	self->priv->accounts = flickr_accounts_load_from_file ();
+	self->priv->account = flickr_accounts_find_default (self->priv->accounts);
+	self->priv->dialog = dialog;
+
+	return self;
+}
+
+
+/* -- flickr_authentication_auto_connect -- */
+
+
+static void
+upload_status_ready_cb (GObject      *source_object,
+			GAsyncResult *res,
+			gpointer      user_data)
+{
+	FlickrAuthentication *self = user_data;
+	FlickrUser           *user;
+	GError               *error = NULL;
+
+	user = flickr_service_get_upload_status_finish (FLICKR_SERVICE (source_object), res, &error);
+	if (error != NULL) {
+		if (self->priv->conn != NULL)
+			gth_task_dialog (GTH_TASK (self->priv->conn), TRUE);
+		_gtk_error_dialog_from_gerror_run (GTK_WINDOW (self->priv->browser), _("Could not connect to the server"), &error);
+		gtk_widget_destroy (self->priv->dialog);
+		return;
+	}
+	flickr_accounts_save_to_file (self->priv->accounts, self->priv->account);
+
+	g_signal_emit (self, flickr_authentication_signals[READY], 0, user);
+
+	g_object_unref (user);
+}
+
+
+static void
+connect_to_server (FlickrAuthentication *self)
+{
+	g_return_if_fail (self->priv->account != NULL);
+
+	flickr_connection_set_auth_token (self->priv->conn, self->priv->account->token);
+	flickr_service_get_upload_status (self->priv->service,
+					  self->priv->cancellable,
+					  upload_status_ready_cb,
+					  self);
+}
+
+
+static void
+set_account (FlickrAuthentication *self,
+	     FlickrAccount        *account)
+{
+	GList *link;
+
+	link = g_list_find_custom (self->priv->accounts, self->priv->account, (GCompareFunc) flickr_account_cmp);
+	if (link != NULL) {
+		self->priv->accounts = g_list_remove_link (self->priv->accounts, link);
+		_g_object_list_unref (link);
+	}
+
+	_g_object_unref (self->priv->account);
+	self->priv->account = NULL;
+
+	if (account != NULL) {
+		self->priv->account = g_object_ref (account);
+		self->priv->accounts = g_list_prepend (self->priv->accounts, g_object_ref (self->priv->account));
+	}
+}
+
+
+static void
+connection_token_ready_cb (GObject      *source_object,
+			   GAsyncResult *res,
+			   gpointer      user_data)
+{
+	FlickrAuthentication *self = user_data;
+	GError               *error = NULL;
+	FlickrAccount        *account;
+
+	if (! flickr_connection_get_token_finish (FLICKR_CONNECTION (source_object), res, &error)) {
+		if (self->priv->conn != NULL)
+			gth_task_dialog (GTH_TASK (self->priv->conn), TRUE);
+		_gtk_error_dialog_from_gerror_run (GTK_WINDOW (self->priv->browser), _("Could not connect to the server"), &error);
+		gtk_widget_destroy (self->priv->dialog);
+		return;
+	}
+
+	account = flickr_account_new ();
+	flickr_account_set_username (account, flickr_connection_get_username (self->priv->conn));
+	flickr_account_set_token (account, flickr_connection_get_auth_token (self->priv->conn));
+	set_account (self, account);
+	g_object_unref (account);
+
+	connect_to_server (self);
+}
+
+
+static void
+complete_authorization_messagedialog_response_cb (GtkDialog *dialog,
+						  int        response_id,
+						  gpointer   user_data)
+{
+	FlickrAuthentication *self = user_data;
+
+	switch (response_id) {
+	case GTK_RESPONSE_HELP:
+		show_help_dialog (GTK_WINDOW (dialog), "flicker-complete-authorization");
+		break;
+
+	case GTK_RESPONSE_DELETE_EVENT:
+	case GTK_RESPONSE_CANCEL:
+		gtk_widget_destroy (GTK_WIDGET (dialog));
+		gtk_widget_destroy (self->priv->dialog);
+		break;
+
+	case GTK_RESPONSE_OK:
+		gtk_widget_destroy (GTK_WIDGET (dialog));
+		gth_task_dialog (GTH_TASK (self->priv->conn), FALSE);
+		flickr_connection_get_token (self->priv->conn,
+					     self->priv->cancellable,
+					     connection_token_ready_cb,
+					     self);
+		break;
+
+	default:
+		break;
+	}
+}
+
+
+static void
+complete_authorization (FlickrAuthentication *self)
+{
+	GtkBuilder *builder;
+	GtkWidget  *dialog;
+
+	gth_task_dialog (GTH_TASK (self->priv->conn), TRUE);
+
+	builder = _gtk_builder_new_from_file ("flicker-complete-authorization.ui", "flicker");
+	dialog = _gtk_builder_get_widget (builder, "complete_authorization_messagedialog");
+	g_object_set_data_full (G_OBJECT (dialog), "builder", builder, g_object_unref);
+	g_signal_connect (dialog,
+			  "response",
+			  G_CALLBACK (complete_authorization_messagedialog_response_cb),
+			  self);
+
+	gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (self->priv->browser));
+	gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
+	gtk_window_present (GTK_WINDOW (dialog));
+}
+
+
+static void
+ask_authorization_messagedialog_response_cb (GtkDialog *dialog,
+					     int        response_id,
+					     gpointer   user_data)
+{
+	FlickrAuthentication *self = user_data;
+
+	switch (response_id) {
+	case GTK_RESPONSE_HELP:
+		show_help_dialog (GTK_WINDOW (dialog), "flicker-ask-authorization");
+		break;
+
+	case GTK_RESPONSE_DELETE_EVENT:
+	case GTK_RESPONSE_CANCEL:
+		gtk_widget_destroy (GTK_WIDGET (dialog));
+		gtk_widget_destroy (self->priv->dialog);
+		break;
+
+	case GTK_RESPONSE_OK:
+		{
+			char   *url;
+			GError *error = NULL;
+
+			gtk_widget_destroy (GTK_WIDGET (dialog));
+
+			url = flickr_connection_get_login_link (self->priv->conn, FLICKR_ACCESS_WRITE);
+			if (gtk_show_uri (gtk_widget_get_screen (GTK_WIDGET (dialog)), url, 0, &error)) {
+				complete_authorization (self);
+			}
+			else {
+				if (self->priv->conn != NULL)
+					gth_task_dialog (GTH_TASK (self->priv->conn), TRUE);
+				_gtk_error_dialog_from_gerror_run (GTK_WINDOW (self->priv->browser), _("Could not connect to the server"), &error);
+				gtk_widget_destroy (self->priv->dialog);
+			}
+
+			g_free (url);
+		}
+		break;
+
+	default:
+		break;
+	}
+}
+
+
+static void
+ask_authorization (FlickrAuthentication *self)
+{
+	GtkBuilder *builder;
+	GtkWidget  *dialog;
+
+	gtk_widget_hide (self->priv->dialog);
+	gth_task_dialog (GTH_TASK (self->priv->conn), TRUE);
+
+	builder = _gtk_builder_new_from_file ("flicker-ask-authorization.ui", "flicker");
+	dialog = _gtk_builder_get_widget (builder, "ask_authorization_messagedialog");
+	g_object_set_data_full (G_OBJECT (dialog), "builder", builder, g_object_unref);
+	g_signal_connect (dialog,
+			  "response",
+			  G_CALLBACK (ask_authorization_messagedialog_response_cb),
+			  self);
+
+	gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (self->priv->browser));
+	gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
+	gtk_window_present (GTK_WINDOW (dialog));
+}
+
+
+static void
+connection_frob_ready_cb (GObject      *source_object,
+			  GAsyncResult *res,
+			  gpointer      user_data)
+{
+	FlickrAuthentication *self = user_data;
+	GError               *error = NULL;
+
+	if (! flickr_connection_get_frob_finish (FLICKR_CONNECTION (source_object), res, &error)) {
+		if (self->priv->conn != NULL)
+			gth_task_dialog (GTH_TASK (self->priv->conn), TRUE);
+		_gtk_error_dialog_from_gerror_run (GTK_WINDOW (self->priv->browser), _("Could not connect to the server"), &error);
+		gtk_widget_destroy (self->priv->dialog);
+		return;
+	}
+
+	ask_authorization (self);
+}
+
+
+static void
+start_authorization_process (FlickrAuthentication *self)
+{
+	flickr_connection_get_frob (self->priv->conn,
+				    self->priv->cancellable,
+				    connection_frob_ready_cb,
+				    self);
+}
+
+
+static void
+account_chooser_dialog_response_cb (GtkDialog *dialog,
+				    int        response_id,
+				    gpointer   user_data)
+{
+	FlickrAuthentication *self = user_data;
+
+	switch (response_id) {
+	case GTK_RESPONSE_DELETE_EVENT:
+	case GTK_RESPONSE_CANCEL:
+		gtk_widget_destroy (GTK_WIDGET (dialog));
+		gtk_widget_destroy (self->priv->dialog);
+		break;
+
+	case GTK_RESPONSE_OK:
+		_g_object_unref (self->priv->account);
+		self->priv->account = flickr_account_chooser_dialog_get_active (FLICKR_ACCOUNT_CHOOSER_DIALOG (dialog));
+		if (self->priv->account != NULL) {
+			gtk_widget_destroy (GTK_WIDGET (dialog));
+			connect_to_server (self);
+		}
+
+		break;
+
+	case FLICKR_ACCOUNT_CHOOSER_RESPONSE_NEW:
+		gtk_widget_destroy (GTK_WIDGET (dialog));
+		start_authorization_process (self);
+		break;
+
+	default:
+		break;
+	}
+}
+
+
+void
+flickr_authentication_auto_connect (FlickrAuthentication *self)
+{
+	gtk_widget_hide (self->priv->dialog);
+	gth_task_dialog (GTH_TASK (self->priv->conn), FALSE);
+
+	if (self->priv->accounts != NULL) {
+		if (self->priv->account != NULL) {
+			connect_to_server (self);
+		}
+		else if (self->priv->accounts->next == NULL) {
+			self->priv->account = g_object_ref (self->priv->accounts->data);
+			connect_to_server (self);
+		}
+		else {
+			GtkWidget *dialog;
+
+			gth_task_dialog (GTH_TASK (self->priv->conn), TRUE);
+			dialog = flickr_account_chooser_dialog_new (self->priv->accounts, self->priv->account);
+			g_signal_connect (dialog,
+					  "response",
+					  G_CALLBACK (account_chooser_dialog_response_cb),
+					  self);
+
+			gtk_window_set_title (GTK_WINDOW (dialog), _("Choose Account"));
+			gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (self->priv->browser));
+			gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
+			gtk_window_present (GTK_WINDOW (dialog));
+		}
+	}
+	else
+		start_authorization_process (self);
+}
+
+
+void
+flickr_authentication_connect (FlickrAuthentication *self,
+			       FlickrAccount        *account)
+{
+	set_account (self, account);
+	flickr_authentication_auto_connect (self);
+}
+
+
+FlickrAccount *
+flickr_authentication_get_account (FlickrAuthentication *self)
+{
+	return self->priv->account;
+}
+
+
+GList *
+flickr_authentication_get_accounts (FlickrAuthentication *self)
+{
+	return self->priv->accounts;
+}
+
+
+/* -- flickr_authentication_edit_accounts -- */
+
+
+static void
+account_manager_dialog_response_cb (GtkDialog *dialog,
+			            int        response_id,
+			            gpointer   user_data)
+{
+	FlickrAuthentication *self = user_data;
+
+	switch (response_id) {
+	case GTK_RESPONSE_DELETE_EVENT:
+	case GTK_RESPONSE_CANCEL:
+		gtk_widget_destroy (GTK_WIDGET (dialog));
+		break;
+
+	case GTK_RESPONSE_OK:
+		_g_object_list_unref (self->priv->accounts);
+		self->priv->accounts = flickr_account_manager_dialog_get_accounts (FLICKR_ACCOUNT_MANAGER_DIALOG (dialog));
+		if (! g_list_find_custom (self->priv->accounts, self->priv->account, (GCompareFunc) flickr_account_cmp)) {
+			_g_object_unref (self->priv->account);
+			self->priv->account = NULL;
+			flickr_authentication_auto_connect (self);
+		}
+		else
+			g_signal_emit (self, flickr_authentication_signals[ACCOUNTS_CHANGED], 0);
+		flickr_accounts_save_to_file (self->priv->accounts, self->priv->account);
+		gtk_widget_destroy (GTK_WIDGET (dialog));
+		break;
+
+	case FLICKR_ACCOUNT_MANAGER_RESPONSE_NEW:
+		gtk_widget_destroy (GTK_WIDGET (dialog));
+		start_authorization_process (self);
+		break;
+
+	default:
+		break;
+	}
+}
+
+
+void
+flickr_authentication_edit_accounts (FlickrAuthentication *self,
+				     GtkWindow            *parent)
+{
+	GtkWidget  *dialog;
+
+	dialog = flickr_account_manager_dialog_new (self->priv->accounts);
+	g_signal_connect (dialog,
+			  "response",
+			  G_CALLBACK (account_manager_dialog_response_cb),
+			  self);
+
+	gtk_window_set_title (GTK_WINDOW (dialog), _("Edit Accounts"));
+	gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (self->priv->dialog));
+	gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
+	gtk_window_present (GTK_WINDOW (dialog));
+}
diff --git a/extensions/flicker/flickr-authentication.h b/extensions/flicker/flickr-authentication.h
new file mode 100644
index 0000000..b084855
--- /dev/null
+++ b/extensions/flicker/flickr-authentication.h
@@ -0,0 +1,77 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ *  GThumb
+ *
+ *  Copyright (C) 2010 Free Software Foundation, Inc.
+ *
+ *  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 2 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, write to the Free Software
+ *  Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef FLICKR_AUTHENTICATION_H
+#define FLICKR_AUTHENTICATION_H
+
+#include <glib.h>
+#include <glib-object.h>
+#include "flickr-account.h"
+#include "flickr-connection.h"
+#include "flickr-service.h"
+#include "flickr-user.h"
+
+G_BEGIN_DECLS
+
+#define FLICKR_TYPE_AUTHENTICATION            (flickr_authentication_get_type ())
+#define FLICKR_AUTHENTICATION(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), FLICKR_TYPE_AUTHENTICATION, FlickrAuthentication))
+#define FLICKR_AUTHENTICATION_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), FLICKR_TYPE_AUTHENTICATION, FlickrAuthenticationClass))
+#define FLICKR_IS_AUTHENTICATION(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), FLICKR_TYPE_AUTHENTICATION))
+#define FLICKR_IS_AUTHENTICATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), FLICKR_TYPE_AUTHENTICATION))
+#define FLICKR_AUTHENTICATION_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), FLICKR_TYPE_AUTHENTICATION, FlickrAuthenticationClass))
+
+typedef struct _FlickrAuthentication FlickrAuthentication;
+typedef struct _FlickrAuthenticationClass FlickrAuthenticationClass;
+typedef struct _FlickrAuthenticationPrivate FlickrAuthenticationPrivate;
+
+struct _FlickrAuthentication {
+	GObject parent_instance;
+	FlickrAuthenticationPrivate *priv;
+};
+
+struct _FlickrAuthenticationClass {
+	GObjectClass parent_class;
+
+	/*< signals >*/
+
+	void  (*ready)             (FlickrAuthentication *auth,
+				    FlickrUser           *user);
+	void  (*accounts_changed)  (FlickrAuthentication *auth);
+};
+
+GType                   flickr_authentication_get_type       (void);
+FlickrAuthentication *  flickr_authentication_new            (FlickrConnection     *conn,
+							      FlickrService        *service,
+							      GCancellable         *cancellable,
+							      GtkWidget            *browser,
+							      GtkWidget            *dialog);
+void                    flickr_authentication_auto_connect   (FlickrAuthentication *auth);
+void                    flickr_authentication_connect        (FlickrAuthentication *auth,
+							      FlickrAccount        *account);
+FlickrAccount *         flickr_authentication_get_account    (FlickrAuthentication *auth);
+GList *                 flickr_authentication_get_accounts   (FlickrAuthentication *auth);
+void                    flickr_authentication_edit_accounts  (FlickrAuthentication *auth,
+							      GtkWindow            *parent);
+
+G_END_DECLS
+
+#endif /* FLICKR_AUTHENTICATION_H */
diff --git a/extensions/flicker/flickr-connection.c b/extensions/flicker/flickr-connection.c
index 6585cf8..49c7ef5 100644
--- a/extensions/flicker/flickr-connection.c
+++ b/extensions/flicker/flickr-connection.c
@@ -28,7 +28,7 @@
 #include "flickr-user.h"
 
 
-#undef DEBUG_FLICKR_CONNECTION
+#undef  DEBUG_FLICKR_CONNECTION
 #define GTHUMB_FLICKR_API_KEY "8960706ee7f4151e893b11837e9c24ce"
 #define GTHUMB_FLICKR_SHARED_SECRET "1ff8d1e45c873423"
 
@@ -306,6 +306,9 @@ flickr_connection_get_frob (FlickrConnection    *self,
 
 	gth_task_progress (GTH_TASK (self), _("Connecting to the server"), NULL, TRUE, 0.0);
 
+	g_free (self->priv->token);
+	self->priv->token = NULL;
+
 	data_set = g_hash_table_new (g_str_hash, g_str_equal);
 	g_hash_table_insert (data_set, "method", "flickr.auth.getFrob");
 	flickr_connection_add_api_sig (self, data_set);



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