[gthumb: 9/22] [picasaweb] added account manager, account free space, etc.



commit 5ee8d734886863703a553f9281dfe38f00d06843
Author: Paolo Bacchilega <paobac src gnome org>
Date:   Tue Jan 26 00:42:30 2010 +0100

    [picasaweb] added account manager, account free space, etc.

 extensions/picasaweb/Makefile.am                   |    4 +
 .../picasaweb/data/ui/export-to-picasaweb.ui       |  172 +++++++--
 .../data/ui/picasa-web-account-manager.ui          |   34 +--
 .../data/ui/picasa-web-album-properties.ui         |   32 ++-
 extensions/picasaweb/dlg-export-to-picasaweb.c     |  390 ++++++++++++++------
 extensions/picasaweb/google-connection.c           |    2 +
 .../picasaweb/picasa-account-chooser-dialog.c      |   17 +-
 .../picasaweb/picasa-account-chooser-dialog.h      |    3 +-
 .../picasaweb/picasa-account-manager-dialog.c      |  271 ++++++++++++++
 .../picasaweb/picasa-account-manager-dialog.h      |   59 +++
 .../picasaweb/picasa-account-properties-dialog.c   |    8 +
 .../picasaweb/picasa-album-properties-dialog.c     |   19 +-
 .../picasaweb/picasa-album-properties-dialog.h     |   12 +-
 extensions/picasaweb/picasa-web-album.c            |   43 +++
 extensions/picasaweb/picasa-web-album.h            |   42 ++-
 extensions/picasaweb/picasa-web-service.c          |   61 ++--
 extensions/picasaweb/picasa-web-service.h          |   15 +-
 extensions/picasaweb/picasa-web-user.c             |  239 ++++++++++++
 extensions/picasaweb/picasa-web-user.h             |   75 ++++
 19 files changed, 1257 insertions(+), 241 deletions(-)
---
diff --git a/extensions/picasaweb/Makefile.am b/extensions/picasaweb/Makefile.am
index bfcb499..0a0532d 100644
--- a/extensions/picasaweb/Makefile.am
+++ b/extensions/picasaweb/Makefile.am
@@ -17,6 +17,8 @@ libpicasaweb_la_SOURCES = 			\
 	main.c					\
 	picasa-account-chooser-dialog.c		\
 	picasa-account-chooser-dialog.h		\
+	picasa-account-manager-dialog.c		\
+	picasa-account-manager-dialog.h		\
 	picasa-account-properties-dialog.c	\
 	picasa-account-properties-dialog.h	\
 	picasa-album-properties-dialog.c	\
@@ -25,6 +27,8 @@ libpicasaweb_la_SOURCES = 			\
 	picasa-web-album.h			\
 	picasa-web-service.c			\
 	picasa-web-service.h			\
+	picasa-web-user.c			\
+	picasa-web-user.h			\
 	preferences.h
 
 libpicasaweb_la_CFLAGS = $(GTHUMB_CFLAGS) $(LIBSOUP_CFLAGS) $(GNOME_KEYRING_CFLAGS) -I$(top_srcdir) -I$(top_builddir)/gthumb 
diff --git a/extensions/picasaweb/data/ui/export-to-picasaweb.ui b/extensions/picasaweb/data/ui/export-to-picasaweb.ui
index 294d1d6..fc061b3 100644
--- a/extensions/picasaweb/data/ui/export-to-picasaweb.ui
+++ b/extensions/picasaweb/data/ui/export-to-picasaweb.ui
@@ -2,32 +2,30 @@
 <interface>
   <requires lib="gtk+" version="2.16"/>
   <!-- interface-naming-policy project-wide -->
-  <object class="GtkListStore" id="account_liststore">
+  <object class="GtkListStore" id="album_liststore">
     <columns>
-      <!-- column-name account -->
-      <column type="gchararray"/>
-      <!-- column-name type -->
-      <column type="gint"/>
+      <!-- column-name data -->
+      <column type="GObject"/>
       <!-- column-name name -->
       <column type="gchararray"/>
       <!-- column-name icon -->
       <column type="gchararray"/>
-      <!-- column-name sensitive -->
-      <column type="gboolean"/>
+      <!-- column-name remaining -->
+      <column type="gchararray"/>
+      <!-- column-name size -->
+      <column type="gchararray"/>
     </columns>
   </object>
-  <object class="GtkListStore" id="album_liststore">
+  <object class="GtkListStore" id="account_liststore">
     <columns>
-      <!-- column-name album -->
-      <column type="GObject"/>
+      <!-- column-name email -->
+      <column type="gchararray"/>
       <!-- column-name type -->
       <column type="gint"/>
       <!-- column-name name -->
       <column type="gchararray"/>
-      <!-- column-name icon -->
+      <!-- column-name icon name -->
       <column type="gchararray"/>
-      <!-- column-name sensitive -->
-      <column type="gboolean"/>
     </columns>
   </object>
   <object class="GtkDialog" id="export_dialog">
@@ -50,11 +48,18 @@
                 <property name="visible">True</property>
                 <property name="spacing">6</property>
                 <child>
-                  <object class="GtkLabel" id="label3">
+                  <object class="GtkAlignment" id="alignment1">
                     <property name="visible">True</property>
-                    <property name="xalign">0</property>
-                    <property name="label" translatable="yes">A_ccount:</property>
-                    <property name="use_underline">True</property>
+                    <property name="top_padding">6</property>
+                    <child>
+                      <object class="GtkLabel" id="label3">
+                        <property name="visible">True</property>
+                        <property name="xalign">0</property>
+                        <property name="yalign">0</property>
+                        <property name="label" translatable="yes">A_ccount:</property>
+                        <property name="use_underline">True</property>
+                      </object>
+                    </child>
                   </object>
                   <packing>
                     <property name="expand">False</property>
@@ -62,23 +67,92 @@
                   </packing>
                 </child>
                 <child>
-                  <object class="GtkComboBox" id="account_combobox">
-                    <property name="width_request">300</property>
+                  <object class="GtkVBox" id="vbox4">
                     <property name="visible">True</property>
-                    <property name="model">account_liststore</property>
+                    <property name="orientation">vertical</property>
+                    <property name="spacing">3</property>
                     <child>
-                      <object class="GtkCellRendererPixbuf" id="cellrenderertext1"/>
-                      <attributes>
-                        <attribute name="sensitive">4</attribute>
-                        <attribute name="icon-name">3</attribute>
-                      </attributes>
+                      <object class="GtkHBox" id="hbox4">
+                        <property name="visible">True</property>
+                        <property name="spacing">6</property>
+                        <child>
+                          <object class="GtkComboBox" id="account_combobox">
+                            <property name="width_request">300</property>
+                            <property name="visible">True</property>
+                            <property name="model">account_liststore</property>
+                            <child>
+                              <object class="GtkCellRendererPixbuf" id="cellrenderertext1"/>
+                              <attributes>
+                                <attribute name="icon-name">3</attribute>
+                              </attributes>
+                            </child>
+                            <child>
+                              <object class="GtkCellRendererText" id="cellrenderertext3"/>
+                              <attributes>
+                                <attribute name="text">2</attribute>
+                              </attributes>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="position">0</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkButton" id="edit_accounts_button">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="receives_default">True</property>
+                            <property name="tooltip_text" translatable="yes">Edit accounts</property>
+                            <child>
+                              <object class="GtkImage" id="image2">
+                                <property name="visible">True</property>
+                                <property name="stock">gtk-edit</property>
+                              </object>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="position">1</property>
+                          </packing>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="position">0</property>
+                      </packing>
                     </child>
                     <child>
-                      <object class="GtkCellRendererText" id="cellrenderertext3"/>
-                      <attributes>
-                        <attribute name="sensitive">4</attribute>
-                        <attribute name="text">2</attribute>
-                      </attributes>
+                      <object class="GtkHBox" id="hbox3">
+                        <property name="visible">True</property>
+                        <property name="spacing">6</property>
+                        <child>
+                          <object class="GtkLabel" id="label1">
+                            <property name="visible">True</property>
+                            <property name="label" translatable="yes">Free space:</property>
+                            <attributes>
+                              <attribute name="absolute-size" value="10000"/>
+                            </attributes>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="position">0</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel" id="free_space_label">
+                            <property name="visible">True</property>
+                            <property name="xalign">0</property>
+                            <property name="yalign">0.51999998092651367</property>
+                            <attributes>
+                              <attribute name="absolute-size" value="10000"/>
+                            </attributes>
+                          </object>
+                          <packing>
+                            <property name="position">1</property>
+                          </packing>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="position">1</property>
+                      </packing>
                     </child>
                   </object>
                   <packing>
@@ -95,6 +169,7 @@
               <object class="GtkVBox" id="vbox2">
                 <property name="visible">True</property>
                 <property name="orientation">vertical</property>
+                <property name="spacing">3</property>
                 <child>
                   <object class="GtkLabel" id="label4">
                     <property name="visible">True</property>
@@ -113,33 +188,57 @@
                     <property name="spacing">6</property>
                     <child>
                       <object class="GtkScrolledWindow" id="scrolledwindow1">
-                        <property name="height_request">150</property>
+                        <property name="width_request">370</property>
+                        <property name="height_request">170</property>
                         <property name="visible">True</property>
                         <property name="can_focus">True</property>
                         <property name="hscrollbar_policy">automatic</property>
                         <property name="vscrollbar_policy">automatic</property>
                         <property name="shadow_type">in</property>
                         <child>
-                          <object class="GtkTreeView" id="treeview1">
+                          <object class="GtkTreeView" id="albums_treeview">
                             <property name="visible">True</property>
                             <property name="can_focus">True</property>
                             <property name="model">album_liststore</property>
-                            <property name="headers_visible">False</property>
                             <property name="headers_clickable">False</property>
+                            <property name="rules_hint">True</property>
                             <property name="search_column">1</property>
                             <child>
                               <object class="GtkTreeViewColumn" id="treeviewcolumn1">
-                                <property name="title">column</property>
+                                <property name="title">Name</property>
+                                <property name="expand">True</property>
                                 <child>
                                   <object class="GtkCellRendererPixbuf" id="cellrendererpixbuf1"/>
                                   <attributes>
-                                    <attribute name="icon-name">3</attribute>
+                                    <attribute name="icon-name">2</attribute>
                                   </attributes>
                                 </child>
                                 <child>
                                   <object class="GtkCellRendererText" id="cellrenderertext5"/>
                                   <attributes>
-                                    <attribute name="text">2</attribute>
+                                    <attribute name="text">1</attribute>
+                                  </attributes>
+                                </child>
+                              </object>
+                            </child>
+                            <child>
+                              <object class="GtkTreeViewColumn" id="treeviewcolumn3">
+                                <property name="title">Used</property>
+                                <child>
+                                  <object class="GtkCellRendererText" id="cellrenderertext4"/>
+                                  <attributes>
+                                    <attribute name="text">4</attribute>
+                                  </attributes>
+                                </child>
+                              </object>
+                            </child>
+                            <child>
+                              <object class="GtkTreeViewColumn" id="treeviewcolumn2">
+                                <property name="title">Remaining photos</property>
+                                <child>
+                                  <object class="GtkCellRendererText" id="cellrenderertext2"/>
+                                  <attributes>
+                                    <attribute name="text">3</attribute>
                                   </attributes>
                                 </child>
                               </object>
@@ -155,6 +254,7 @@
                       <object class="GtkVBox" id="vbox3">
                         <property name="visible">True</property>
                         <property name="orientation">vertical</property>
+                        <property name="spacing">6</property>
                         <child>
                           <object class="GtkButton" id="add_album_button">
                             <property name="visible">True</property>
diff --git a/extensions/picasaweb/data/ui/picasa-web-account-manager.ui b/extensions/picasaweb/data/ui/picasa-web-account-manager.ui
index ea42ea6..bfbb35b 100644
--- a/extensions/picasaweb/data/ui/picasa-web-account-manager.ui
+++ b/extensions/picasaweb/data/ui/picasa-web-account-manager.ui
@@ -4,8 +4,8 @@
   <!-- interface-naming-policy project-wide -->
   <object class="GtkListStore" id="accounts_liststore">
     <columns>
-      <!-- column-name account -->
-      <column type="gpointer"/>
+      <!-- column-name data -->
+      <column type="gchararray"/>
       <!-- column-name name -->
       <column type="gchararray"/>
     </columns>
@@ -18,7 +18,9 @@
       <object class="GtkLabel" id="label3">
         <property name="visible">True</property>
         <property name="xalign">0</property>
-        <property name="label" translatable="yes">Accounts:</property>
+        <property name="label" translatable="yes">A_ccounts:</property>
+        <property name="use_underline">True</property>
+        <property name="mnemonic_widget">account_treeview</property>
       </object>
       <packing>
         <property name="expand">False</property>
@@ -45,11 +47,12 @@
                 <property name="model">accounts_liststore</property>
                 <property name="headers_visible">False</property>
                 <property name="headers_clickable">False</property>
+                <property name="reorderable">True</property>
                 <property name="search_column">1</property>
                 <child>
                   <object class="GtkTreeViewColumn" id="treeviewcolumn1">
                     <child>
-                      <object class="GtkCellRendererText" id="cellrenderertext1"/>
+                      <object class="GtkCellRendererText" id="account_cellrenderertext"/>
                       <attributes>
                         <attribute name="text">1</attribute>
                       </attributes>
@@ -69,7 +72,7 @@
             <property name="orientation">vertical</property>
             <property name="spacing">6</property>
             <child>
-              <object class="GtkButton" id="button6">
+              <object class="GtkButton" id="add_button">
                 <property name="visible">True</property>
                 <property name="can_focus">True</property>
                 <property name="receives_default">True</property>
@@ -86,24 +89,7 @@
               </packing>
             </child>
             <child>
-              <object class="GtkButton" id="button7">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">True</property>
-                <child>
-                  <object class="GtkImage" id="image2">
-                    <property name="visible">True</property>
-                    <property name="stock">gtk-properties</property>
-                  </object>
-                </child>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="position">1</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkButton" id="button8">
+              <object class="GtkButton" id="delete_button">
                 <property name="visible">True</property>
                 <property name="can_focus">True</property>
                 <property name="receives_default">True</property>
@@ -116,7 +102,7 @@
               </object>
               <packing>
                 <property name="expand">False</property>
-                <property name="position">2</property>
+                <property name="position">1</property>
               </packing>
             </child>
           </object>
diff --git a/extensions/picasaweb/data/ui/picasa-web-album-properties.ui b/extensions/picasaweb/data/ui/picasa-web-album-properties.ui
index d877a1b..9393a02 100644
--- a/extensions/picasaweb/data/ui/picasa-web-album-properties.ui
+++ b/extensions/picasaweb/data/ui/picasa-web-album-properties.ui
@@ -8,7 +8,7 @@
     <child>
       <object class="GtkTable" id="table1">
         <property name="visible">True</property>
-        <property name="n_rows">2</property>
+        <property name="n_rows">3</property>
         <property name="n_columns">2</property>
         <property name="column_spacing">6</property>
         <property name="row_spacing">6</property>
@@ -44,8 +44,8 @@
             <property name="use_underline">True</property>
           </object>
           <packing>
-            <property name="top_attach">1</property>
-            <property name="bottom_attach">2</property>
+            <property name="top_attach">2</property>
+            <property name="bottom_attach">3</property>
             <property name="x_options">GTK_FILL</property>
           </packing>
         </child>
@@ -73,6 +73,32 @@
           <packing>
             <property name="left_attach">1</property>
             <property name="right_attach">2</property>
+            <property name="top_attach">2</property>
+            <property name="bottom_attach">3</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkEntry" id="description_entry">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="invisible_char">&#x25CF;</property>
+          </object>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="right_attach">2</property>
+            <property name="top_attach">1</property>
+            <property name="bottom_attach">2</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel" id="label3">
+            <property name="visible">True</property>
+            <property name="xalign">0</property>
+            <property name="label" translatable="yes">_Description:</property>
+            <property name="use_underline">True</property>
+            <property name="mnemonic_widget">description_entry</property>
+          </object>
+          <packing>
             <property name="top_attach">1</property>
             <property name="bottom_attach">2</property>
           </packing>
diff --git a/extensions/picasaweb/dlg-export-to-picasaweb.c b/extensions/picasaweb/dlg-export-to-picasaweb.c
index a355258..9ed54c9 100644
--- a/extensions/picasaweb/dlg-export-to-picasaweb.c
+++ b/extensions/picasaweb/dlg-export-to-picasaweb.c
@@ -28,10 +28,12 @@
 #include <gthumb.h>
 #include "dlg-export-to-picasaweb.h"
 #include "picasa-account-chooser-dialog.h"
+#include "picasa-account-manager-dialog.h"
 #include "picasa-account-properties-dialog.h"
 #include "picasa-album-properties-dialog.h"
 #include "picasa-web-album.h"
 #include "picasa-web-service.h"
+#include "picasa-web-user.h"
 
 
 #define GET_WIDGET(x) (_gtk_builder_get_widget (data->builder, (x)))
@@ -45,20 +47,19 @@ typedef enum {
 
 
 enum {
-	ACCOUNT_DATA_COLUMN,
+	ACCOUNT_EMAIL_COLUMN,
 	ACCOUNT_TYPE_COLUMN,
 	ACCOUNT_NAME_COLUMN,
-	ACCOUNT_ICON_COLUMN,
-	ACCOUNT_SENSITIVE_COLUMN
+	ACCOUNT_ICON_COLUMN
 };
 
 
 enum {
 	ALBUM_DATA_COLUMN,
-	ALBUM_TYPE_COLUMN,
 	ALBUM_NAME_COLUMN,
 	ALBUM_ICON_COLUMN,
-	ALBUM_SENSITIVE_COLUMN
+	ALBUM_REMAINING_IMAGES_COLUMN,
+	ALBUM_USED_BYTES_COLUMN
 };
 
 
@@ -68,6 +69,7 @@ typedef struct {
 	GtkWidget        *dialog;
 	GtkWidget        *progress_dialog;
 	GList            *accounts;
+	PicasaWebUser    *user;
 	char             *email;
 	char             *password;
 	char             *challange;
@@ -92,6 +94,7 @@ export_dialog_destroy_cb (GtkWidget  *widget,
 	g_free (data->challange);
 	g_free (data->password);
 	g_free (data->email);
+	_g_object_unref (data->user);
 	_g_string_list_free (data->accounts);
 	_g_object_unref (data->builder);
 	g_free (data);
@@ -112,7 +115,7 @@ export_dialog_response_cb (GtkDialog *dialog,
 
 	case GTK_RESPONSE_DELETE_EVENT:
 	case GTK_RESPONSE_CANCEL:
-		picasa_web_accounts_save_to_file (data->accounts);
+		picasa_web_accounts_save_to_file (data->accounts, data->email);
 		gtk_widget_destroy (data->dialog);
 		break;
 
@@ -126,79 +129,93 @@ export_dialog_response_cb (GtkDialog *dialog,
 
 
 static void
-update_album_list (DialogData *data)
-{
-	GtkTreeIter  iter;
-	GList       *scan;
-
-	gtk_list_store_clear (GTK_LIST_STORE (GET_WIDGET ("album_liststore")));
-
-	for (scan = data->albums; scan; scan = scan->next) {
-		PicasaWebAlbum *album = scan->data;
-
-		gtk_list_store_append (GTK_LIST_STORE (GET_WIDGET ("album_liststore")), &iter);
-		gtk_list_store_set (GTK_LIST_STORE (GET_WIDGET ("album_liststore")), &iter,
-				    ALBUM_DATA_COLUMN, album,
-				    ALBUM_TYPE_COLUMN, ITEM_TYPE_ENTRY,
-				    ALBUM_ICON_COLUMN, "file-catalog",
-				    ALBUM_NAME_COLUMN, album->title,
-				    ALBUM_SENSITIVE_COLUMN, TRUE,
-				    -1);
-	}
-
-	gtk_widget_set_sensitive (GET_WIDGET ("upload_button"), data->albums != NULL);
-}
-
-
-static void
-show_export_dialog (DialogData *data)
+update_account_list (DialogData *data)
 {
 	GtkTreeIter  iter;
 	int          current_account;
 	int          idx;
 	GList       *scan;
 
-	/* Accounts */
-
-	gtk_list_store_clear (GTK_LIST_STORE (GET_WIDGET ("account_liststore")));
-
 	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++) {
 		char *account = scan->data;
 
 		if (g_strcmp0 (account, data->email) == 0)
 			current_account = 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,
-				    ACCOUNT_DATA_COLUMN, account,
+				    ACCOUNT_EMAIL_COLUMN, account,
 				    ACCOUNT_TYPE_COLUMN, ITEM_TYPE_ENTRY,
 				    ACCOUNT_NAME_COLUMN, account,
-				    ACCOUNT_SENSITIVE_COLUMN, TRUE,
 				    -1);
 	}
 
+	/* FIXME
 	gtk_list_store_append (GTK_LIST_STORE (GET_WIDGET ("account_liststore")), &iter);
 	gtk_list_store_set (GTK_LIST_STORE (GET_WIDGET ("account_liststore")), &iter,
 			    ACCOUNT_TYPE_COLUMN, ITEM_TYPE_SEPARATOR,
-			    ACCOUNT_SENSITIVE_COLUMN, TRUE,
 			    -1);
 
 	gtk_list_store_append (GTK_LIST_STORE (GET_WIDGET ("account_liststore")), &iter);
 	gtk_list_store_set (GTK_LIST_STORE (GET_WIDGET ("account_liststore")), &iter,
-			    ACCOUNT_DATA_COLUMN, NULL,
+			    ACCOUNT_EMAIL_COLUMN, NULL,
 			    ACCOUNT_TYPE_COLUMN, ITEM_TYPE_COMMAND,
 			    ACCOUNT_ICON_COLUMN, GTK_STOCK_EDIT,
 			    ACCOUNT_NAME_COLUMN, _("Edit Accounts..."),
-			    ACCOUNT_SENSITIVE_COLUMN, TRUE,
 			    -1);
+	*/
 
 	gtk_combo_box_set_active (GTK_COMBO_BOX (GET_WIDGET ("account_combobox")), current_account);
+}
 
-	update_album_list (data);
 
-	/**/
+static void
+update_album_list (DialogData *data)
+{
+	GtkTreeIter  iter;
+	GList       *scan;
+	char        *free_space;
+
+	g_return_if_fail (data->user != NULL);
+
+	free_space = g_format_size_for_display (data->user->quota_limit - data->user->quota_current);
+	gtk_label_set_text (GTK_LABEL (GET_WIDGET ("free_space_label")), free_space);
+	g_free (free_space);
+
+	gtk_list_store_clear (GTK_LIST_STORE (GET_WIDGET ("album_liststore")));
+	for (scan = data->albums; scan; scan = scan->next) {
+		PicasaWebAlbum *album = scan->data;
+		char           *n_photos_remaining;
+		char           *used_bytes;
+
+		n_photos_remaining = g_strdup_printf ("%d", album->n_photos_remaining);
+		used_bytes = g_format_size_for_display (album->used_bytes);
+
+		gtk_list_store_append (GTK_LIST_STORE (GET_WIDGET ("album_liststore")), &iter);
+		gtk_list_store_set (GTK_LIST_STORE (GET_WIDGET ("album_liststore")), &iter,
+				    ALBUM_DATA_COLUMN, album,
+				    ALBUM_ICON_COLUMN, "file-catalog",
+				    ALBUM_NAME_COLUMN, album->title,
+				    ALBUM_REMAINING_IMAGES_COLUMN, n_photos_remaining,
+				    ALBUM_USED_BYTES_COLUMN, used_bytes,
+				    -1);
+
+		g_free (used_bytes);
+		g_free (n_photos_remaining);
+	}
+
+	gtk_widget_set_sensitive (GET_WIDGET ("upload_button"), data->albums != NULL);
+}
+
 
-	gth_task_dialog (GTH_TASK (data->conn), TRUE); /* FIXME */
+static void
+show_export_dialog (DialogData *data)
+{
+	update_account_list (data);
+	update_album_list (data);
+	gth_task_dialog (GTH_TASK (data->conn), TRUE);
 
 	gtk_window_set_transient_for (GTK_WINDOW (data->dialog), GTK_WINDOW (data->browser));
 	gtk_window_set_modal (GTK_WINDOW (data->dialog), FALSE);
@@ -223,6 +240,8 @@ list_albums_ready_cb (GObject      *source_object,
 		return;
 	}
 
+	_g_object_unref (data->user);
+	data->user = g_object_ref (picasa_web_service_get_user (picasaweb));
 	show_export_dialog (data);
 }
 
@@ -250,7 +269,9 @@ store_password_done_cb (GnomeKeyringResult result,
 #endif
 
 
-static void challange_account_dialog (DialogData *data);
+static void account_properties_dialog (DialogData *data,
+			               const char *email);
+static void challange_account_dialog  (DialogData *data);
 
 
 static void
@@ -266,6 +287,9 @@ connection_ready_cb (GObject      *source_object,
 		if (g_error_matches (error, GOOGLE_CONNECTION_ERROR, GOOGLE_CONNECTION_ERROR_CAPTCHA_REQUIRED)) {
 			challange_account_dialog (data);
 		}
+		else if (g_error_matches (error, GOOGLE_CONNECTION_ERROR, GOOGLE_CONNECTION_ERROR_BAD_AUTHENTICATION)) {
+			account_properties_dialog (data, data->email);
+		}
 		else {
 			_gtk_error_dialog_from_gerror_show (GTK_WINDOW (data->browser), _("Could not connect to the server"), &error);
 			gtk_widget_destroy (data->dialog);
@@ -297,48 +321,19 @@ connection_ready_cb (GObject      *source_object,
 }
 
 
-static void
-connect_to_server (DialogData *data)
-{
-	if (data->conn == NULL) {
-		data->conn = google_connection_new (GOOGLE_SERVICE_PICASA_WEB_ALBUM);
-		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));
-	}
-
-#ifdef HAVE_GNOME_KEYRING
-	if (data->password == NULL) {
-		if (gnome_keyring_is_available ()) {
-			gnome_keyring_find_password_sync (GNOME_KEYRING_NETWORK_PASSWORD,
-							  &data->password,
-							  "user", data->email,
-							  "server", "picasaweb.google.com",
-							  "protocol", "http",
-							  NULL);
-		}
-	}
-#endif
-
-	google_connection_connect (data->conn,
-				   data->email,
-				   data->password,
-				   data->challange,
-				   data->cancellable,
-				   connection_ready_cb,
-				   data);
-}
+static void connect_to_server (DialogData *data);
 
 
 static void
-challange_account_dialog_response_cb (GtkDialog *dialog,
-				      int        response_id,
-				      gpointer   user_data)
+account_properties_dialog_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), "challange-picasaweb-account");
+		show_help_dialog (GTK_WINDOW (dialog), "picasaweb-account-properties");
 		break;
 
 	case GTK_RESPONSE_DELETE_EVENT:
@@ -350,9 +345,10 @@ challange_account_dialog_response_cb (GtkDialog *dialog,
 	case GTK_RESPONSE_OK:
 		g_free (data->email);
 		g_free (data->password);
+		g_free (data->challange);
 		data->email = g_strdup (picasa_account_properties_dialog_get_email (PICASA_ACCOUNT_PROPERTIES_DIALOG (dialog)));
 		data->password = g_strdup (picasa_account_properties_dialog_get_password (PICASA_ACCOUNT_PROPERTIES_DIALOG (dialog)));
-		data->challange = g_strdup (picasa_account_properties_dialog_get_challange (PICASA_ACCOUNT_PROPERTIES_DIALOG (dialog)));
+		data->challange = NULL;
 		gtk_widget_destroy (GTK_WIDGET (dialog));
 		connect_to_server (data);
 		break;
@@ -364,16 +360,21 @@ challange_account_dialog_response_cb (GtkDialog *dialog,
 
 
 static void
-challange_account_dialog (DialogData *data)
+account_properties_dialog (DialogData *data,
+			   const char *email)
 {
 	GtkWidget *dialog;
 
-	dialog = picasa_account_properties_dialog_new (data->email, data->password, google_connection_get_challange_url (data->conn));
+	if (data->conn != NULL)
+		gth_task_dialog (GTH_TASK (data->conn), TRUE);
+
+	dialog = picasa_account_properties_dialog_new (email, NULL, NULL);
 	g_signal_connect (dialog,
 			  "response",
-			  G_CALLBACK (challange_account_dialog_response_cb),
+			  G_CALLBACK (account_properties_dialog_response_cb),
 			  data);
 
+	gtk_window_set_title (GTK_WINDOW (dialog), _("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));
@@ -381,15 +382,77 @@ challange_account_dialog (DialogData *data)
 
 
 static void
-new_account_dialog_response_cb (GtkDialog *dialog,
-				int        response_id,
-				gpointer   user_data)
+connect_to_server_step2 (DialogData *data)
+{
+	if (data->password == NULL) {
+		gth_task_dialog (GTH_TASK (data->conn), TRUE);
+		account_properties_dialog (data, data->email);
+	}
+	else {
+		gth_task_dialog (GTH_TASK (data->conn), FALSE);
+		google_connection_connect (data->conn,
+					   data->email,
+					   data->password,
+					   data->challange,
+					   data->cancellable,
+					   connection_ready_cb,
+					   data);
+	}
+}
+
+
+#ifdef HAVE_GNOME_KEYRING
+static void
+find_password_cb (GnomeKeyringResult result,
+                  const char        *string,
+                  gpointer           user_data)
+{
+	DialogData *data = user_data;
+
+	if (string != NULL)
+		data->password = g_strdup (string);
+	connect_to_server_step2 (data);
+}
+#endif
+
+
+static void
+connect_to_server (DialogData *data)
+{
+	if (data->conn == NULL) {
+		data->conn = google_connection_new (GOOGLE_SERVICE_PICASA_WEB_ALBUM);
+		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));
+	}
+
+#ifdef HAVE_GNOME_KEYRING
+	if ((data->password == NULL) && gnome_keyring_is_available ()) {
+		gnome_keyring_find_password (GNOME_KEYRING_NETWORK_PASSWORD,
+					     find_password_cb,
+					     data,
+					     NULL,
+					     "user", data->email,
+					     "server", "picasaweb.google.com",
+					     "protocol", "http",
+					     NULL);
+		return;
+	}
+#endif
+
+	connect_to_server_step2 (data);
+}
+
+
+static void
+challange_account_dialog_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), "new-picasaweb-account");
+		show_help_dialog (GTK_WINDOW (dialog), "picasaweb-account-challange");
 		break;
 
 	case GTK_RESPONSE_DELETE_EVENT:
@@ -401,10 +464,9 @@ new_account_dialog_response_cb (GtkDialog *dialog,
 	case GTK_RESPONSE_OK:
 		g_free (data->email);
 		g_free (data->password);
-		g_free (data->challange);
 		data->email = g_strdup (picasa_account_properties_dialog_get_email (PICASA_ACCOUNT_PROPERTIES_DIALOG (dialog)));
 		data->password = g_strdup (picasa_account_properties_dialog_get_password (PICASA_ACCOUNT_PROPERTIES_DIALOG (dialog)));
-		data->challange = NULL;
+		data->challange = g_strdup (picasa_account_properties_dialog_get_challange (PICASA_ACCOUNT_PROPERTIES_DIALOG (dialog)));
 		gtk_widget_destroy (GTK_WIDGET (dialog));
 		connect_to_server (data);
 		break;
@@ -416,17 +478,16 @@ new_account_dialog_response_cb (GtkDialog *dialog,
 
 
 static void
-new_account_dialog (DialogData *data)
+challange_account_dialog (DialogData *data)
 {
 	GtkWidget *dialog;
 
-	dialog = picasa_account_properties_dialog_new (NULL, NULL, NULL);
+	dialog = picasa_account_properties_dialog_new (data->email, data->password, google_connection_get_challange_url (data->conn));
 	g_signal_connect (dialog,
 			  "response",
-			  G_CALLBACK (new_account_dialog_response_cb),
+			  G_CALLBACK (challange_account_dialog_response_cb),
 			  data);
 
-	gtk_window_set_title (GTK_WINDOW (dialog), _("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));
@@ -441,6 +502,7 @@ account_chooser_dialog_response_cb (GtkDialog *dialog,
 	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);
@@ -457,11 +519,12 @@ account_chooser_dialog_response_cb (GtkDialog *dialog,
 			gtk_widget_destroy (GTK_WIDGET (dialog));
 			connect_to_server (data);
 		}
+
 		break;
 
 	case PICASA_ACCOUNT_CHOOSER_RESPONSE_NEW:
 		gtk_widget_destroy (GTK_WIDGET (dialog));
-		new_account_dialog (data);
+		account_properties_dialog (data, NULL);
 		break;
 
 	default:
@@ -512,6 +575,7 @@ new_album_dialog_response_cb (GtkDialog *dialog,
 	DialogData *data = user_data;
 
 	switch (response_id) {
+	case GTK_RESPONSE_DELETE_EVENT:
 	case GTK_RESPONSE_CANCEL:
 		gtk_widget_destroy (GTK_WIDGET (dialog));
 		break;
@@ -546,7 +610,7 @@ add_album_button_clicked_cb (GtkButton *button,
 	DialogData *data = user_data;
 	GtkWidget  *dialog;
 
-	dialog = picasa_album_properties_dialog_new (NULL, PICASA_WEB_ACCESS_PUBLIC);  /* FIXME: use the current catalog/folder name as default value */
+	dialog = picasa_album_properties_dialog_new (NULL, NULL, PICASA_WEB_ACCESS_PUBLIC);  /* FIXME: use the current catalog/folder name as default value */
 	g_signal_connect (dialog,
 			  "response",
 			  G_CALLBACK (new_album_dialog_response_cb),
@@ -556,14 +620,113 @@ add_album_button_clicked_cb (GtkButton *button,
 	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
+auto_select_account (DialogData *data)
+{
+	gtk_widget_hide (data->dialog);
+
+	if (data->accounts != NULL) {
+		/* FIXME: remove comment when done
+		if (data->email != NULL) {
+			connect_to_server (data);
+		}
+		else if (data->accounts->next == NULL) {
+			data->email = g_strdup ((char *)data->accounts->data);
+			connect_to_server (data);
+		}
+		else {*/
+			GtkWidget *dialog;
+
+			dialog = picasa_account_chooser_dialog_new (data->accounts, data->email);
+			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
+		account_properties_dialog (data, NULL);
+}
+
+
+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_string_list_free (data->accounts);
+		data->accounts = picasa_account_manager_dialog_get_accounts (PICASA_ACCOUNT_MANAGER_DIALOG (dialog));
+		if (! g_list_find_custom (data->accounts, data->email, (GCompareFunc) strcmp)) {
+			g_free (data->email);
+			data->email = NULL;
+			auto_select_account (data);
+		}
+		else
+			update_account_list (data);
+		picasa_web_accounts_save_to_file (data->accounts, data->email);
+		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 = picasa_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->browser));
+	gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
+	gtk_window_present (GTK_WINDOW (dialog));
+}
+
+
+static void
+albums_treeview_selection_changed_cb (GtkTreeSelection *treeselection,
+				      gpointer          user_data)
+{
+	DialogData *data = user_data;
+	gboolean    selected;
+
+	selected = gtk_tree_selection_get_selected (treeselection, NULL, NULL);
+	gtk_widget_set_sensitive (GET_WIDGET ("upload_button"), selected);
 }
 
 
 void
 dlg_export_to_picasaweb (GthBrowser *browser)
 {
-	DialogData *data;
+	DialogData       *data;
+	GtkTreeSelection *selection;
 
 	data = g_new0 (DialogData, 1);
 	data->browser = browser;
@@ -577,6 +740,7 @@ dlg_export_to_picasaweb (GthBrowser *browser)
 					      account_combobox_row_separator_func,
 					      data,
 					      NULL);
+	gtk_widget_set_sensitive (GET_WIDGET ("upload_button"), FALSE);
 
 	/* Set the signals handlers. */
 
@@ -592,28 +756,18 @@ dlg_export_to_picasaweb (GthBrowser *browser)
 			  "clicked",
 			  G_CALLBACK (add_album_button_clicked_cb),
 			  data);
+	g_signal_connect (GET_WIDGET ("edit_accounts_button"),
+			  "clicked",
+			  G_CALLBACK (edit_accounts_button_clicked_cb),
+			  data);
 
-	data->accounts = picasa_web_accounts_load_from_file ();
-	if (data->accounts != NULL) {
-		if (data->accounts->next != NULL) { /* FIXME: == */
-			data->email = g_strdup ((char *)data->accounts->data);
-			connect_to_server (data);
-		}
-		else {
-			GtkWidget *dialog;
-
-			dialog = picasa_account_chooser_dialog_new (data->accounts);
-			g_signal_connect (dialog,
-					  "response",
-					  G_CALLBACK (account_chooser_dialog_response_cb),
-					  data);
+	selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (GET_WIDGET ("albums_treeview")));
+	gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
+	g_signal_connect (selection,
+			  "changed",
+			  G_CALLBACK (albums_treeview_selection_changed_cb),
+			  data);
 
-			gtk_window_set_title (GTK_WINDOW (dialog), _("Choose Account"));
-			gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (browser));
-			gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
-			gtk_window_present (GTK_WINDOW (dialog));
-		}
-	}
-	else
-		new_account_dialog (data);
+	data->accounts = picasa_web_accounts_load_from_file (&data->email);
+	auto_select_account (data);
 }
diff --git a/extensions/picasaweb/google-connection.c b/extensions/picasaweb/google-connection.c
index c25f4d3..d3c8e06 100644
--- a/extensions/picasaweb/google-connection.c
+++ b/extensions/picasaweb/google-connection.c
@@ -357,6 +357,8 @@ google_connection_connect (GoogleConnection    *self,
 							user_data,
 							google_connection_connect);
 
+	gth_task_progress (GTH_TASK (self), _("Connecting to the server"), NULL, TRUE, 0.0);
+
 	data_set = g_hash_table_new (g_str_hash, g_str_equal);
 	g_hash_table_insert (data_set, "accountType", "HOSTED_OR_GOOGLE");
 	g_hash_table_insert (data_set, "service", self->priv->service);
diff --git a/extensions/picasaweb/picasa-account-chooser-dialog.c b/extensions/picasaweb/picasa-account-chooser-dialog.c
index 22186c3..720f8b6 100644
--- a/extensions/picasaweb/picasa-account-chooser-dialog.c
+++ b/extensions/picasaweb/picasa-account-chooser-dialog.c
@@ -137,16 +137,22 @@ picasa_account_chooser_dialog_get_type (void)
 
 static void
 picasa_account_chooser_dialog_construct (PicasaAccountChooserDialog *self,
-				         GList                   *accounts)
+				         GList                      *accounts,
+				         const char                 *_default)
 {
 	GtkTreeIter  iter;
 	GList       *scan;
+	int          active = 0;
+	int          idx;
 
 	gtk_list_store_clear (GTK_LIST_STORE (GET_WIDGET ("account_liststore")));
 
-	for (scan = accounts; scan; scan = scan->next) {
+	for (scan = accounts, idx = 0; scan; scan = scan->next, idx++) {
 		char *account = scan->data;
 
+		if (g_strcmp0 (account, _default) == 0)
+			active = 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,
 				    ACCOUNT_DATA_COLUMN, account,
@@ -156,17 +162,18 @@ picasa_account_chooser_dialog_construct (PicasaAccountChooserDialog *self,
 				    -1);
 	}
 
-	gtk_combo_box_set_active (GTK_COMBO_BOX (GET_WIDGET ("account_combobox")), 0);
+	gtk_combo_box_set_active (GTK_COMBO_BOX (GET_WIDGET ("account_combobox")), active);
 }
 
 
 GtkWidget *
-picasa_account_chooser_dialog_new (GList *accounts)
+picasa_account_chooser_dialog_new (GList      *accounts,
+				   const char *_default)
 {
 	PicasaAccountChooserDialog *self;
 
 	self = g_object_new (PICASA_TYPE_ACCOUNT_CHOOSER_DIALOG, NULL);
-	picasa_account_chooser_dialog_construct (self, accounts);
+	picasa_account_chooser_dialog_construct (self, accounts, _default);
 
 	return (GtkWidget *) self;
 }
diff --git a/extensions/picasaweb/picasa-account-chooser-dialog.h b/extensions/picasaweb/picasa-account-chooser-dialog.h
index fbc93fd..ec54bbc 100644
--- a/extensions/picasaweb/picasa-account-chooser-dialog.h
+++ b/extensions/picasaweb/picasa-account-chooser-dialog.h
@@ -51,7 +51,8 @@ struct _PicasaAccountChooserDialogClass {
 };
 
 GType          picasa_account_chooser_dialog_get_type    (void);
-GtkWidget *    picasa_account_chooser_dialog_new         (GList *accounts);
+GtkWidget *    picasa_account_chooser_dialog_new         (GList      *accounts,
+							  const char *_default);
 char *         picasa_account_chooser_dialog_get_active  (PicasaAccountChooserDialog *self);
 
 G_END_DECLS
diff --git a/extensions/picasaweb/picasa-account-manager-dialog.c b/extensions/picasaweb/picasa-account-manager-dialog.c
new file mode 100644
index 0000000..b042120
--- /dev/null
+++ b/extensions/picasaweb/picasa-account-manager-dialog.c
@@ -0,0 +1,271 @@
+/* -*- 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/gi18n.h>
+#include "picasa-account-manager-dialog.h"
+#include "picasa-account-properties-dialog.h"
+
+
+#define GET_WIDGET(x) (_gtk_builder_get_widget (self->priv->builder, (x)))
+
+
+enum {
+	ACCOUNT_DATA_COLUMN,
+	ACCOUNT_NAME_COLUMN,
+};
+
+
+static gpointer parent_class = NULL;
+
+
+struct _PicasaAccountManagerDialogPrivate {
+	GtkBuilder *builder;
+};
+
+
+static void
+picasa_account_manager_dialog_finalize (GObject *object)
+{
+	PicasaAccountManagerDialog *self;
+
+	self = PICASA_ACCOUNT_MANAGER_DIALOG (object);
+
+	_g_object_unref (self->priv->builder);
+
+	G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+
+static void
+picasa_account_manager_dialog_class_init (PicasaAccountManagerDialogClass *klass)
+{
+	GObjectClass *object_class;
+
+	parent_class = g_type_class_peek_parent (klass);
+	g_type_class_add_private (klass, sizeof (PicasaAccountManagerDialogPrivate));
+
+	object_class = (GObjectClass*) klass;
+	object_class->finalize = picasa_account_manager_dialog_finalize;
+}
+
+
+static void
+text_renderer_edited_cb (GtkCellRendererText *renderer,
+			 char                *path,
+			 char                *new_text,
+			 gpointer             user_data)
+{
+	PicasaAccountManagerDialog *self = user_data;
+	GtkTreePath                *tree_path;
+	GtkTreeIter                 iter;
+
+	tree_path = gtk_tree_path_new_from_string (path);
+	tree_path = gtk_tree_path_new_from_string (path);
+	if (! gtk_tree_model_get_iter (GTK_TREE_MODEL (GET_WIDGET ("accounts_liststore")),
+				       &iter,
+				       tree_path))
+	{
+		gtk_tree_path_free (tree_path);
+		return;
+	}
+	gtk_tree_path_free (tree_path);
+
+	gtk_list_store_set (GTK_LIST_STORE (GET_WIDGET ("accounts_liststore")), &iter,
+			    ACCOUNT_DATA_COLUMN, new_text,
+			    ACCOUNT_NAME_COLUMN, new_text,
+			    -1);
+}
+
+
+static void
+add_button_clicked_cb (GtkWidget *button,
+		       gpointer   user_data)
+{
+	PicasaAccountManagerDialog *self = user_data;
+	GtkListStore               *list_store;
+	GtkTreeIter                 iter;
+	GtkTreePath                *tree_path;
+	GtkTreeViewColumn          *tree_column;
+
+	list_store = GTK_LIST_STORE (GET_WIDGET ("accounts_liststore"));
+	gtk_list_store_append (list_store, &iter);
+	gtk_list_store_set (list_store, &iter,
+			    ACCOUNT_DATA_COLUMN, "",
+			    ACCOUNT_NAME_COLUMN, "",
+			    -1);
+
+	tree_path = gtk_tree_model_get_path (GTK_TREE_MODEL (list_store), &iter);
+	tree_column = gtk_tree_view_get_column (GTK_TREE_VIEW (GET_WIDGET ("account_treeview")), 0);
+	gtk_tree_view_set_cursor (GTK_TREE_VIEW (GET_WIDGET ("account_treeview")),
+				  tree_path,
+				  tree_column,
+				  TRUE);
+
+	gtk_tree_path_free (tree_path);
+}
+
+
+static void
+delete_button_clicked_cb (GtkWidget *button,
+		          gpointer   user_data)
+{
+	PicasaAccountManagerDialog *self = user_data;
+	GtkTreeModel               *tree_model;
+	GtkTreeIter                 iter;
+
+	if (gtk_tree_selection_get_selected (gtk_tree_view_get_selection (GTK_TREE_VIEW (GET_WIDGET ("account_treeview"))),
+					     &tree_model,
+					     &iter))
+	{
+		gtk_list_store_remove (GTK_LIST_STORE (tree_model), &iter);
+	}
+}
+
+
+static void
+picasa_account_manager_dialog_init (PicasaAccountManagerDialog *self)
+{
+	GtkWidget *content;
+
+	self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, PICASA_TYPE_ACCOUNT_MANAGER_DIALOG, PicasaAccountManagerDialogPrivate);
+	self->priv->builder = _gtk_builder_new_from_file ("picasa-web-account-manager.ui", "picasaweb");
+
+	gtk_window_set_resizable (GTK_WINDOW (self), FALSE);
+	gtk_dialog_set_has_separator (GTK_DIALOG (self), FALSE);
+	gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (self))), 5);
+	gtk_container_set_border_width (GTK_CONTAINER (self), 5);
+
+	content = _gtk_builder_get_widget (self->priv->builder, "account_manager");
+	gtk_container_set_border_width (GTK_CONTAINER (content), 5);
+	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_CANCEL,
+			       GTK_RESPONSE_CANCEL);
+	gtk_dialog_add_button (GTK_DIALOG (self),
+			       GTK_STOCK_OK,
+			       GTK_RESPONSE_OK);
+
+	g_object_set (GET_WIDGET ("account_cellrenderertext"), "editable", TRUE, NULL);
+        g_signal_connect (GET_WIDGET ("account_cellrenderertext"),
+                          "edited",
+                          G_CALLBACK (text_renderer_edited_cb),
+                          self);
+
+	g_signal_connect (GET_WIDGET ("add_button"),
+			  "clicked",
+			  G_CALLBACK (add_button_clicked_cb),
+			  self);
+	g_signal_connect (GET_WIDGET ("delete_button"),
+			  "clicked",
+			  G_CALLBACK (delete_button_clicked_cb),
+			  self);
+}
+
+
+GType
+picasa_account_manager_dialog_get_type (void)
+{
+	static GType type = 0;
+
+	if (type == 0) {
+		static const GTypeInfo g_define_type_info = {
+			sizeof (PicasaAccountManagerDialogClass),
+			(GBaseInitFunc) NULL,
+			(GBaseFinalizeFunc) NULL,
+			(GClassInitFunc) picasa_account_manager_dialog_class_init,
+			(GClassFinalizeFunc) NULL,
+			NULL,
+			sizeof (PicasaAccountManagerDialog),
+			0,
+			(GInstanceInitFunc) picasa_account_manager_dialog_init,
+			NULL
+		};
+		type = g_type_register_static (GTK_TYPE_DIALOG,
+					       "PicasaAccountManagerDialog",
+					       &g_define_type_info,
+					       0);
+	}
+
+	return type;
+}
+
+
+static void
+picasa_account_manager_dialog_construct (PicasaAccountManagerDialog *self,
+				         GList                      *accounts)
+{
+	GtkListStore *list_store;
+	GtkTreeIter   iter;
+	GList        *scan;
+
+	list_store = GTK_LIST_STORE (GET_WIDGET ("accounts_liststore"));
+	gtk_list_store_clear (list_store);
+	for (scan = accounts; scan; scan = scan->next) {
+		char *account = scan->data;
+
+		gtk_list_store_append (list_store, &iter);
+		gtk_list_store_set (list_store, &iter,
+				    ACCOUNT_DATA_COLUMN, account,
+				    ACCOUNT_NAME_COLUMN, account,
+				    -1);
+	}
+}
+
+
+GtkWidget *
+picasa_account_manager_dialog_new (GList *accounts)
+{
+	PicasaAccountManagerDialog *self;
+
+	self = g_object_new (PICASA_TYPE_ACCOUNT_MANAGER_DIALOG, NULL);
+	picasa_account_manager_dialog_construct (self, accounts);
+
+	return (GtkWidget *) self;
+}
+
+
+GList *
+picasa_account_manager_dialog_get_accounts (PicasaAccountManagerDialog *self)
+{
+	GList        *accounts;
+	GtkTreeModel *tree_model;
+	GtkTreeIter   iter;
+
+	tree_model = (GtkTreeModel *) GET_WIDGET ("accounts_liststore");
+	if (! gtk_tree_model_get_iter_first (tree_model, &iter))
+		return NULL;
+
+	accounts = NULL;
+	do {
+		char *account;
+
+		gtk_tree_model_get (tree_model, &iter,
+				    ACCOUNT_DATA_COLUMN, &account,
+				    -1);
+		accounts = g_list_prepend (accounts, account);
+	}
+	while (gtk_tree_model_iter_next (tree_model, &iter));
+
+	return g_list_reverse (accounts);
+}
diff --git a/extensions/picasaweb/picasa-account-manager-dialog.h b/extensions/picasaweb/picasa-account-manager-dialog.h
new file mode 100644
index 0000000..55cf2b7
--- /dev/null
+++ b/extensions/picasaweb/picasa-account-manager-dialog.h
@@ -0,0 +1,59 @@
+/* -*- 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 PICASA_ACCOUNT_MANAGER_DIALOG_H
+#define PICASA_ACCOUNT_MANAGER_DIALOG_H
+
+#include <gtk/gtk.h>
+#include <gthumb.h>
+
+G_BEGIN_DECLS
+
+#define PICASA_ACCOUNT_MANAGER_RESPONSE_NEW 1
+
+#define PICASA_TYPE_ACCOUNT_MANAGER_DIALOG            (picasa_account_manager_dialog_get_type ())
+#define PICASA_ACCOUNT_MANAGER_DIALOG(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), PICASA_TYPE_ACCOUNT_MANAGER_DIALOG, PicasaAccountManagerDialog))
+#define PICASA_ACCOUNT_MANAGER_DIALOG_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), PICASA_TYPE_ACCOUNT_MANAGER_DIALOG, PicasaAccountManagerDialogClass))
+#define PICASA_IS_ACCOUNT_MANAGER_DIALOG(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PICASA_TYPE_ACCOUNT_MANAGER_DIALOG))
+#define PICASA_IS_ACCOUNT_MANAGER_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PICASA_TYPE_ACCOUNT_MANAGER_DIALOG))
+#define PICASA_ACCOUNT_MANAGER_DIALOG_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), PICASA_TYPE_ACCOUNT_MANAGER_DIALOG, PicasaAccountManagerDialogClass))
+
+typedef struct _PicasaAccountManagerDialog PicasaAccountManagerDialog;
+typedef struct _PicasaAccountManagerDialogClass PicasaAccountManagerDialogClass;
+typedef struct _PicasaAccountManagerDialogPrivate PicasaAccountManagerDialogPrivate;
+
+struct _PicasaAccountManagerDialog {
+	GtkDialog parent_instance;
+	PicasaAccountManagerDialogPrivate *priv;
+};
+
+struct _PicasaAccountManagerDialogClass {
+	GtkDialogClass parent_class;
+};
+
+GType          picasa_account_manager_dialog_get_type     (void);
+GtkWidget *    picasa_account_manager_dialog_new          (GList                      *accounts);
+GList *        picasa_account_manager_dialog_get_accounts (PicasaAccountManagerDialog *dialog);
+
+G_END_DECLS
+
+#endif /* PICASA_ACCOUNT_MANAGER_DIALOG_H */
diff --git a/extensions/picasaweb/picasa-account-properties-dialog.c b/extensions/picasaweb/picasa-account-properties-dialog.c
index aa74fe3..2d959ef 100644
--- a/extensions/picasaweb/picasa-account-properties-dialog.c
+++ b/extensions/picasaweb/picasa-account-properties-dialog.c
@@ -174,6 +174,14 @@ picasa_account_properties_dialog_construct (PicasaAccountPropertiesDialog *self,
 		g_object_unref (file);
 		g_free (url);
 	}
+
+	if (email == NULL)
+		gtk_widget_grab_focus (GET_WIDGET ("email_entry"));
+	else if (password == NULL)
+		gtk_widget_grab_focus (GET_WIDGET ("password_entry"));
+	else
+		gtk_widget_grab_focus (GET_WIDGET ("challenge_entry"));
+
 }
 
 
diff --git a/extensions/picasaweb/picasa-album-properties-dialog.c b/extensions/picasaweb/picasa-album-properties-dialog.c
index 89603d6..4b922af 100644
--- a/extensions/picasaweb/picasa-album-properties-dialog.c
+++ b/extensions/picasaweb/picasa-album-properties-dialog.c
@@ -116,23 +116,27 @@ picasa_album_properties_dialog_get_type (void)
 
 static void
 picasa_album_properties_dialog_construct (PicasaAlbumPropertiesDialog *self,
-				       const char               *name,
-				       PicasaWebAccess           access)
+				          const char                  *name,
+				          const char                  *description,
+				          PicasaWebAccess              access)
 {
 	if (name != NULL)
 		gtk_entry_set_text (GTK_ENTRY (GET_WIDGET ("name_entry")), name);
+	if (description != NULL)
+		gtk_entry_set_text (GTK_ENTRY (GET_WIDGET ("description_entry")), description);
 	gtk_combo_box_set_active (GTK_COMBO_BOX (GET_WIDGET ("visibility_combobox")), (access == PICASA_WEB_ACCESS_PUBLIC) ? 0 : 1);
 }
 
 
 GtkWidget *
 picasa_album_properties_dialog_new (const char      *name,
-				 PicasaWebAccess  access)
+				    const char      *description,
+				    PicasaWebAccess  access)
 {
 	PicasaAlbumPropertiesDialog *self;
 
 	self = g_object_new (PICASA_TYPE_ALBUM_PROPERTIES_DIALOG, NULL);
-	picasa_album_properties_dialog_construct (self, name, access);
+	picasa_album_properties_dialog_construct (self, name, description, access);
 
 	return (GtkWidget *) self;
 }
@@ -145,6 +149,13 @@ picasa_album_properties_dialog_get_name (PicasaAlbumPropertiesDialog *self)
 }
 
 
+const char *
+picasa_album_properties_dialog_get_description (PicasaAlbumPropertiesDialog *self)
+{
+	return gtk_entry_get_text (GTK_ENTRY (GET_WIDGET ("description_entry")));
+}
+
+
 PicasaWebAccess
 picasa_album_properties_dialog_get_access (PicasaAlbumPropertiesDialog *self)
 {
diff --git a/extensions/picasaweb/picasa-album-properties-dialog.h b/extensions/picasaweb/picasa-album-properties-dialog.h
index fdb9845..4fed152 100644
--- a/extensions/picasaweb/picasa-album-properties-dialog.h
+++ b/extensions/picasaweb/picasa-album-properties-dialog.h
@@ -49,11 +49,13 @@ struct _PicasaAlbumPropertiesDialogClass {
 	GtkDialogClass parent_class;
 };
 
-GType            picasa_album_properties_dialog_get_type      (void);
-GtkWidget *      picasa_album_properties_dialog_new           (const char                  *name,
-							       PicasaWebAccess              access);
-const char *     picasa_album_properties_dialog_get_name      (PicasaAlbumPropertiesDialog *self);
-PicasaWebAccess  picasa_album_properties_dialog_get_access    (PicasaAlbumPropertiesDialog *self);
+GType            picasa_album_properties_dialog_get_type        (void);
+GtkWidget *      picasa_album_properties_dialog_new             (const char                  *name,
+								 const char                  *description,
+							         PicasaWebAccess              access);
+const char *     picasa_album_properties_dialog_get_name        (PicasaAlbumPropertiesDialog *self);
+const char *     picasa_album_properties_dialog_get_description (PicasaAlbumPropertiesDialog *self);
+PicasaWebAccess  picasa_album_properties_dialog_get_access      (PicasaAlbumPropertiesDialog *self);
 
 G_END_DECLS
 
diff --git a/extensions/picasaweb/picasa-web-album.c b/extensions/picasaweb/picasa-web-album.c
index e135782..4e006bf 100644
--- a/extensions/picasaweb/picasa-web-album.c
+++ b/extensions/picasaweb/picasa-web-album.c
@@ -75,6 +75,8 @@ picasa_web_album_create_element (DomDomizable *base,
 		dom_element_append_child (element, dom_document_create_element_with_text (doc, self->title, "title", "type", "text", NULL));
 	if (self->summary != NULL)
 		dom_element_append_child (element, dom_document_create_element_with_text (doc, self->summary, "summary", "type", "text", NULL));
+	if (self->location != NULL)
+		dom_element_append_child (element, dom_document_create_element_with_text (doc, self->location, "gphoto:location", NULL));
 
 	switch (self->access) {
 	case PICASA_WEB_ACCESS_ALL:
@@ -117,6 +119,8 @@ picasa_web_album_load_from_element (DomDomizable *base,
 	picasa_web_album_set_edit_url (self, NULL);
 	picasa_web_album_set_access (self, NULL);
 	self->n_photos = 0;
+	self->n_photos_remaining = 0;
+	self->used_bytes = 0;
 
 	picasa_web_album_set_etag (self, dom_element_get_attribute (element, "gd:etag"));
 	for (node = element->first_child; node; node = node->next_sibling) {
@@ -129,6 +133,9 @@ picasa_web_album_load_from_element (DomDomizable *base,
 		else if (g_strcmp0 (node->tag_name, "summary") == 0) {
 			picasa_web_album_set_summary (self, dom_element_get_inner_text (node));
 		}
+		else if (g_strcmp0 (node->tag_name, "gphoto:location") == 0) {
+			picasa_web_album_set_location (self, dom_element_get_inner_text (node));
+		}
 		else if (g_strcmp0 (node->tag_name, "link") == 0) {
 			if (g_strcmp0 (dom_element_get_attribute (node, "rel"), "edit") == 0)
 				picasa_web_album_set_edit_url (self, dom_element_get_attribute (node, "href"));
@@ -139,6 +146,12 @@ picasa_web_album_load_from_element (DomDomizable *base,
 		else if (g_strcmp0 (node->tag_name, "gphoto:numphotos") == 0) {
 			picasa_web_album_set_n_photos (self, dom_element_get_inner_text (node));
 		}
+		else if (g_strcmp0 (node->tag_name, "gphoto:numphotosremaining") == 0) {
+			picasa_web_album_set_n_photos_remaining (self, dom_element_get_inner_text (node));
+		}
+		else if (g_strcmp0 (node->tag_name, "gphoto:bytesUsed") == 0) {
+			picasa_web_album_set_used_bytes (self, dom_element_get_inner_text (node));
+		}
 	}
 }
 
@@ -244,6 +257,17 @@ picasa_web_album_set_summary (PicasaWebAlbum *self,
 
 
 void
+picasa_web_album_set_location (PicasaWebAlbum *self,
+			       const char     *value)
+{
+	g_free (self->location);
+	self->location = NULL;
+	if (value != NULL)
+		self->location = g_strdup (value);
+}
+
+
+void
 picasa_web_album_set_edit_url (PicasaWebAlbum *self,
 			       const char     *value)
 {
@@ -274,6 +298,14 @@ picasa_web_album_set_access (PicasaWebAlbum *self,
 
 
 void
+picasa_web_album_set_used_bytes (PicasaWebAlbum *self,
+				 const char     *value)
+{
+	self->used_bytes = g_ascii_strtoull (value, NULL, 10);
+}
+
+
+void
 picasa_web_album_set_n_photos (PicasaWebAlbum *self,
 			       const char     *value)
 {
@@ -282,3 +314,14 @@ picasa_web_album_set_n_photos (PicasaWebAlbum *self,
 	else
 		self->n_photos = 0;
 }
+
+
+void
+picasa_web_album_set_n_photos_remaining (PicasaWebAlbum *self,
+					 const char     *value)
+{
+	if (value != NULL)
+		self->n_photos_remaining = atoi (value);
+	else
+		self->n_photos_remaining = 0;
+}
diff --git a/extensions/picasaweb/picasa-web-album.h b/extensions/picasaweb/picasa-web-album.h
index d4afe7b..16e714e 100644
--- a/extensions/picasaweb/picasa-web-album.h
+++ b/extensions/picasaweb/picasa-web-album.h
@@ -54,31 +54,41 @@ struct _PicasaWebAlbum {
 	char            *id;
 	char            *title;
 	char            *summary;
+	char            *location;
 	char            *edit_url;
 	PicasaWebAccess  access;
 	int              n_photos;
+	int              n_photos_remaining;
+	goffset          used_bytes;
 };
 
 struct _PicasaWebAlbumClass {
 	GObjectClass parent_class;
 };
 
-GType             picasa_web_album_get_type     (void);
-PicasaWebAlbum *  picasa_web_album_new          (void);
-void              picasa_web_album_set_etag     (PicasaWebAlbum *self,
-						 const char     *value);
-void              picasa_web_album_set_id       (PicasaWebAlbum *self,
-						 const char     *value);
-void              picasa_web_album_set_title    (PicasaWebAlbum *self,
-						 const char     *value);
-void              picasa_web_album_set_summary  (PicasaWebAlbum *self,
-						 const char     *value);
-void              picasa_web_album_set_edit_url (PicasaWebAlbum *self,
-						 const char     *value);
-void              picasa_web_album_set_access   (PicasaWebAlbum *self,
-						 const char     *value);
-void              picasa_web_album_set_n_photos (PicasaWebAlbum *self,
-						 const char     *value);
+GType             picasa_web_album_get_type          (void);
+PicasaWebAlbum *  picasa_web_album_new               (void);
+void              picasa_web_album_set_etag          (PicasaWebAlbum *self,
+						      const char     *value);
+void              picasa_web_album_set_id            (PicasaWebAlbum *self,
+						      const char     *value);
+void              picasa_web_album_set_title         (PicasaWebAlbum *self,
+						      const char     *value);
+void              picasa_web_album_set_summary       (PicasaWebAlbum *self,
+						      const char     *value);
+void              picasa_web_album_set_location      (PicasaWebAlbum *self,
+						      const char     *value);
+void              picasa_web_album_set_edit_url      (PicasaWebAlbum *self,
+						      const char     *value);
+void              picasa_web_album_set_access        (PicasaWebAlbum *self,
+						      const char     *value);
+void              picasa_web_album_set_used_bytes    (PicasaWebAlbum *self,
+						      const char     *value);
+void              picasa_web_album_set_n_photos      (PicasaWebAlbum *self,
+						      const char     *value);
+void              picasa_web_album_set_n_photos_remaining
+						     (PicasaWebAlbum *self,
+						      const char     *value);
 
 G_END_DECLS
 
diff --git a/extensions/picasaweb/picasa-web-service.c b/extensions/picasaweb/picasa-web-service.c
index 3ac5fcf..8b79976 100644
--- a/extensions/picasaweb/picasa-web-service.c
+++ b/extensions/picasaweb/picasa-web-service.c
@@ -31,7 +31,7 @@
 struct _PicasaWebServicePrivate
 {
 	GoogleConnection *conn;
-	char             *user_id;
+	PicasaWebUser    *user;
 };
 
 
@@ -45,7 +45,7 @@ picasa_web_service_finalize (GObject *object)
 
 	self = PICASA_WEB_SERVICE (object);
 	_g_object_unref (self->priv->conn);
-	g_free (self->priv->user_id);
+	_g_object_unref (self->priv->user);
 
 	G_OBJECT_CLASS (parent_class)->finalize (object);
 }
@@ -69,7 +69,7 @@ picasa_web_service_init (PicasaWebService *self)
 {
 	self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, PICASA_TYPE_WEB_SERVICE, PicasaWebServicePrivate);
 	self->priv->conn = NULL;
-	self->priv->user_id = g_strdup ("default");
+	self->priv->user = NULL;
 }
 
 
@@ -113,6 +113,13 @@ picasa_web_service_new (GoogleConnection *conn)
 }
 
 
+PicasaWebUser *
+picasa_web_service_get_user (PicasaWebService *self)
+{
+	return self->priv->user;
+}
+
+
 /* -- picasa_web_service_list_albums -- */
 
 
@@ -151,22 +158,17 @@ list_albums_ready_cb (SoupSession *session,
 
 		if (feed_node != NULL) {
 			DomElement     *node;
-			PicasaWebAlbum *album = NULL;
+			PicasaWebAlbum *album;
+
+			self->priv->user = picasa_web_user_new ();
+			dom_domizable_load_from_element (DOM_DOMIZABLE (self->priv->user), feed_node);
 
+			album = NULL;
 			for (node = feed_node->first_child;
 			     node != NULL;
 			     node = node->next_sibling)
 			{
-				if (g_strcmp0 (node->tag_name, "id") == 0) { /* get the user id */
-					char *user_id;
-
-					user_id = strrchr (dom_element_get_inner_text (node), '/');
-					if (user_id != NULL) {
-						g_free (self->priv->user_id);
-						self->priv->user_id = g_strdup (user_id + 1);
-					}
-				}
-				else if (g_strcmp0 (node->tag_name, "entry") == 0) { /* read the album data */
+				if (g_strcmp0 (node->tag_name, "entry") == 0) { /* read the album data */
 					if (album != NULL)
 						albums = g_list_prepend (albums, album);
 					album = picasa_web_album_new ();
@@ -202,6 +204,8 @@ picasa_web_service_list_albums (PicasaWebService    *self,
 
 	g_return_if_fail (user_id != NULL);
 
+	gth_task_progress (GTH_TASK (self->priv->conn), _("Getting the album list"), NULL, TRUE, 0.0);
+
 	url = g_strconcat ("http://picasaweb.google.com/data/feed/api/user/";, user_id, NULL);
 	msg = soup_message_new ("GET", url);
 	google_connection_send_message (self->priv->conn,
@@ -289,7 +293,9 @@ picasa_web_service_create_album (PicasaWebService     *self,
 	char        *url;
 	SoupMessage *msg;
 
-	g_return_if_fail (self->priv->user_id != NULL);
+	g_return_if_fail (self->priv->user != NULL);
+
+	gth_task_progress (GTH_TASK (self->priv->conn), _("Creating the new album"), NULL, TRUE, 0.0);
 
 	doc = dom_document_new ();
 	entry = dom_domizable_create_element (DOM_DOMIZABLE (album), doc);
@@ -299,7 +305,7 @@ picasa_web_service_create_album (PicasaWebService     *self,
 	dom_element_append_child (DOM_ELEMENT (doc), entry);
 	buffer = dom_document_dump (doc, &len);
 
-	url = g_strconcat ("http://picasaweb.google.com/data/feed/api/user/";, self->priv->user_id, NULL);
+	url = g_strconcat ("http://picasaweb.google.com/data/feed/api/user/";, self->priv->user->id, NULL);
 	msg = soup_message_new ("POST", url);
 	soup_message_set_request (msg, ATOM_ENTRY_MIME_TYPE, SOUP_MEMORY_TAKE, buffer, len);
 	google_connection_send_message (self->priv->conn,
@@ -332,7 +338,7 @@ picasa_web_service_create_album_finish (PicasaWebService  *service,
 
 
 GList *
-picasa_web_accounts_load_from_file (void)
+picasa_web_accounts_load_from_file (char **_default)
 {
 	GList       *accounts = NULL;
 	char        *filename;
@@ -364,6 +370,8 @@ picasa_web_accounts_load_from_file (void)
 					value = dom_element_get_attribute (child, "email");
 					if (value != NULL)
 						accounts = g_list_prepend (accounts, g_strdup (value));
+					if ((_default != NULL)  && (g_strcmp0 (dom_element_get_attribute (child, "default"), "1") == 0))
+						*_default = g_strdup (value);
 				}
 			}
 
@@ -380,7 +388,8 @@ picasa_web_accounts_load_from_file (void)
 
 
 void
-picasa_web_accounts_save_to_file (GList *accounts)
+picasa_web_accounts_save_to_file (GList      *accounts,
+				  const char *_default)
 {
 	DomDocument *doc;
 	DomElement  *root;
@@ -393,11 +402,17 @@ picasa_web_accounts_save_to_file (GList *accounts)
 	doc = dom_document_new ();
 	root = dom_document_create_element (doc, "accounts", NULL);
 	dom_element_append_child (DOM_ELEMENT (doc), root);
-	for (scan = accounts; scan; scan = scan->next)
-		dom_element_append_child (root,
-					  dom_document_create_element (doc, "account",
-								       "email", (char *) scan->data,
-								       NULL));
+	for (scan = accounts; scan; scan = scan->next) {
+		const char *email = scan->data;
+		DomElement *node;
+
+		node = dom_document_create_element (doc, "account",
+						    "email", email,
+						    NULL);
+		if (g_strcmp0 (email, _default) == 0)
+			dom_element_set_attribute (node, "default", "1");
+		dom_element_append_child (root, node);
+	}
 
 	gth_user_dir_make_dir_for_file (GTH_DIR_CONFIG, GTHUMB_DIR, "accounts", "picasaweb.xml", NULL);
 	filename = gth_user_dir_get_file (GTH_DIR_CONFIG, GTHUMB_DIR, "accounts", "picasaweb.xml", NULL);
diff --git a/extensions/picasaweb/picasa-web-service.h b/extensions/picasaweb/picasa-web-service.h
index d99e5b8..d6e2fdb 100644
--- a/extensions/picasaweb/picasa-web-service.h
+++ b/extensions/picasaweb/picasa-web-service.h
@@ -26,6 +26,7 @@
 #include <glib-object.h>
 #include "google-connection.h"
 #include "picasa-web-album.h"
+#include "picasa-web-user.h"
 
 #define PICASA_TYPE_WEB_SERVICE         (picasa_web_service_get_type ())
 #define PICASA_WEB_SERVICE(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), PICASA_TYPE_WEB_SERVICE, PicasaWebService))
@@ -51,26 +52,28 @@ struct _PicasaWebServiceClass
 
 GType                picasa_web_service_get_type            (void) G_GNUC_CONST;
 PicasaWebService *   picasa_web_service_new                 (GoogleConnection     *conn);
-void                 picasa_web_service_list_albums         (PicasaWebService     *service,
+PicasaWebUser *      picasa_web_service_get_user            (PicasaWebService     *self);
+void                 picasa_web_service_list_albums         (PicasaWebService     *self,
 						             const char           *user_id,
 						             GCancellable         *cancellable,
 						             GAsyncReadyCallback   callback,
 						             gpointer              user_data);
-GList *              picasa_web_service_list_albums_finish  (PicasaWebService     *service,
+GList *              picasa_web_service_list_albums_finish  (PicasaWebService     *self,
 						             GAsyncResult         *result,
 						             GError              **error);
-void                 picasa_web_service_create_album        (PicasaWebService     *service,
+void                 picasa_web_service_create_album        (PicasaWebService     *self,
 							     PicasaWebAlbum       *album,
 							     GCancellable         *cancellable,
 							     GAsyncReadyCallback   callback,
 							     gpointer              user_data);
-PicasaWebAlbum *     picasa_web_service_create_album_finish (PicasaWebService     *service,
+PicasaWebAlbum *     picasa_web_service_create_album_finish (PicasaWebService     *self,
 							     GAsyncResult         *result,
 							     GError              **error);
 
 /* utilities */
 
-GList *              picasa_web_accounts_load_from_file    (void);
-void                 picasa_web_accounts_save_to_file      (GList *accounts);
+GList *              picasa_web_accounts_load_from_file    (char       **_default);
+void                 picasa_web_accounts_save_to_file      (GList       *accounts,
+							    const char  *_default);
 
 #endif /* PICASA_WEB_SERVICE_H */
diff --git a/extensions/picasaweb/picasa-web-user.c b/extensions/picasaweb/picasa-web-user.c
new file mode 100644
index 0000000..12f6c10
--- /dev/null
+++ b/extensions/picasaweb/picasa-web-user.c
@@ -0,0 +1,239 @@
+/* -*- 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 <stdlib.h>
+#include <string.h>
+#include <gthumb.h>
+#include "picasa-web-user.h"
+
+
+static gpointer picasa_web_user_parent_class = NULL;
+
+
+static void
+picasa_web_user_finalize (GObject *obj)
+{
+	PicasaWebUser *self;
+
+	self = PICASA_WEB_USER (obj);
+
+	g_free (self->id);
+	g_free (self->nickname);
+	g_free (self->icon);
+
+	G_OBJECT_CLASS (picasa_web_user_parent_class)->finalize (obj);
+}
+
+
+static void
+picasa_web_user_class_init (PicasaWebUserClass *klass)
+{
+	picasa_web_user_parent_class = g_type_class_peek_parent (klass);
+	G_OBJECT_CLASS (klass)->finalize = picasa_web_user_finalize;
+}
+
+
+static DomElement*
+picasa_web_user_create_element (DomDomizable *base,
+				DomDocument  *doc)
+{
+	PicasaWebUser *self;
+	DomElement    *element;
+
+	self = PICASA_WEB_USER (base);
+
+	element = dom_document_create_element (doc, "entry",
+					       "xmlns", "http://www.w3.org/2005/Atom";,
+					       "xmlns:media", "http://search.yahoo.com/mrss/";,
+					       "xmlns:gphoto", "http://schemas.google.com/photos/2007";,
+					       NULL);
+	if (self->id != NULL)
+		dom_element_append_child (element, dom_document_create_element_with_text (doc, self->id, "gphoto:user", NULL));
+	if (self->nickname != NULL)
+		dom_element_append_child (element, dom_document_create_element_with_text (doc, self->nickname, "gphoto:nickname", NULL));
+	if (self->icon != NULL)
+		dom_element_append_child (element, dom_document_create_element_with_text (doc, self->icon, "icon", NULL));
+
+	dom_element_append_child (element,
+				  dom_document_create_element (doc, "category",
+							       "scheme", "http://schemas.google.com/g/2005#kind";,
+							       "term", "http://schemas.google.com/photos/2007#user";,
+							       NULL));
+
+	return element;
+}
+
+
+static void
+picasa_web_user_load_from_element (DomDomizable *base,
+				   DomElement   *element)
+{
+	PicasaWebUser *self;
+	DomElement    *node;
+
+	self = PICASA_WEB_USER (base);
+
+	picasa_web_user_set_id (self, NULL);
+	picasa_web_user_set_nickname (self, NULL);
+	picasa_web_user_set_icon (self, NULL);
+	self->quota_limit = 0;
+	self->quota_current = 0;
+	self->max_photos_per_album = 0;
+
+	for (node = element->first_child; node; node = node->next_sibling) {
+		if (g_strcmp0 (node->tag_name, "gphoto:user") == 0) {
+			picasa_web_user_set_id (self, dom_element_get_inner_text (node));
+		}
+		else if (g_strcmp0 (node->tag_name, "gphoto:nickname") == 0) {
+			picasa_web_user_set_nickname (self, dom_element_get_inner_text (node));
+		}
+		else if (g_strcmp0 (node->tag_name, "icon") == 0) {
+			picasa_web_user_set_icon (self, dom_element_get_inner_text (node));
+		}
+		else if (g_strcmp0 (node->tag_name, "gphoto:quotalimit") == 0) {
+			picasa_web_user_set_quota_limit (self, dom_element_get_inner_text (node));
+		}
+		else if (g_strcmp0 (node->tag_name, "gphoto:quotacurrent") == 0) {
+			picasa_web_user_set_quota_current (self, dom_element_get_inner_text (node));
+		}
+		else if (g_strcmp0 (node->tag_name, "gphoto:maxPhotosPerAlbum") == 0) {
+			picasa_web_user_set_max_photos (self, dom_element_get_inner_text (node));
+		}
+	}
+}
+
+
+static void
+picasa_web_user_dom_domizable_interface_init (DomDomizableIface *iface)
+{
+	iface->create_element = picasa_web_user_create_element;
+	iface->load_from_element = picasa_web_user_load_from_element;
+}
+
+
+static void
+picasa_web_user_instance_init (PicasaWebUser *self)
+{
+}
+
+
+GType
+picasa_web_user_get_type (void)
+{
+	static GType picasa_web_user_type_id = 0;
+
+	if (picasa_web_user_type_id == 0) {
+		static const GTypeInfo g_define_type_info = {
+			sizeof (PicasaWebUserClass),
+			(GBaseInitFunc) NULL,
+			(GBaseFinalizeFunc) NULL,
+			(GClassInitFunc) picasa_web_user_class_init,
+			(GClassFinalizeFunc) NULL,
+			NULL,
+			sizeof (PicasaWebUser),
+			0,
+			(GInstanceInitFunc) picasa_web_user_instance_init,
+			NULL
+		};
+		static const GInterfaceInfo dom_domizable_info = {
+			(GInterfaceInitFunc) picasa_web_user_dom_domizable_interface_init,
+			(GInterfaceFinalizeFunc) NULL,
+			NULL
+		};
+
+		picasa_web_user_type_id = g_type_register_static (G_TYPE_OBJECT,
+								  "PicasaWebUser",
+								  &g_define_type_info,
+								  0);
+		g_type_add_interface_static (picasa_web_user_type_id, DOM_TYPE_DOMIZABLE, &dom_domizable_info);
+	}
+
+	return picasa_web_user_type_id;
+}
+
+
+PicasaWebUser *
+picasa_web_user_new (void)
+{
+	return g_object_new (PICASA_WEB_TYPE_USER, NULL);
+}
+
+
+void
+picasa_web_user_set_id (PicasaWebUser *self,
+			const char    *value)
+{
+	g_free (self->id);
+	self->id = NULL;
+	if (value != NULL)
+		self->id = g_strdup (value);
+}
+
+
+void
+picasa_web_user_set_nickname (PicasaWebUser *self,
+			      const char    *value)
+{
+	g_free (self->nickname);
+	self->nickname = NULL;
+	if (value != NULL)
+		self->nickname = g_strdup (value);
+}
+
+
+void
+picasa_web_user_set_icon (PicasaWebUser *self,
+			  const char    *value)
+{
+	g_free (self->icon);
+	self->icon = NULL;
+	if (value != NULL)
+		self->icon = g_strdup (value);
+}
+
+
+void
+picasa_web_user_set_quota_limit (PicasaWebUser *self,
+				 const char    *value)
+{
+	self->quota_limit = g_ascii_strtoull (value, NULL, 10);
+}
+
+
+void
+picasa_web_user_set_quota_current (PicasaWebUser *self,
+				   const char    *value)
+{
+	self->quota_current = g_ascii_strtoull (value, NULL, 10);
+}
+
+
+void
+picasa_web_user_set_max_photos (PicasaWebUser *self,
+			        const char     *value)
+{
+	if (value != NULL)
+		self->max_photos_per_album = atoi (value);
+	else
+		self->max_photos_per_album = 0;
+}
diff --git a/extensions/picasaweb/picasa-web-user.h b/extensions/picasaweb/picasa-web-user.h
new file mode 100644
index 0000000..fc92b06
--- /dev/null
+++ b/extensions/picasaweb/picasa-web-user.h
@@ -0,0 +1,75 @@
+/* -*- 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 PICASA_WEB_USER_H
+#define PICASA_WEB_USER_H
+
+#include <glib.h>
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define PICASA_WEB_TYPE_USER            (picasa_web_user_get_type ())
+#define PICASA_WEB_USER(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), PICASA_WEB_TYPE_USER, PicasaWebUser))
+#define PICASA_WEB_USER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), PICASA_WEB_TYPE_USER, PicasaWebUserClass))
+#define PICASA_WEB_IS_USER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PICASA_WEB_TYPE_USER))
+#define PICASA_WEB_IS_USER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PICASA_WEB_TYPE_USER))
+#define PICASA_WEB_USER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), PICASA_WEB_TYPE_USER, PicasaWebUserClass))
+
+typedef struct _PicasaWebUser PicasaWebUser;
+typedef struct _PicasaWebUserClass PicasaWebUserClass;
+typedef struct _PicasaWebUserPrivate PicasaWebUserPrivate;
+
+struct _PicasaWebUser {
+	GObject parent_instance;
+	PicasaWebUserPrivate *priv;
+
+	char    *id;
+	char    *nickname;
+	char    *icon;
+	goffset  quota_limit;
+	goffset  quota_current;
+	goffset  max_photos_per_album;
+};
+
+struct _PicasaWebUserClass {
+	GObjectClass parent_class;
+};
+
+GType             picasa_web_user_get_type          (void);
+PicasaWebUser *   picasa_web_user_new               (void);
+void              picasa_web_user_set_id            (PicasaWebUser *self,
+						     const char    *value);
+void              picasa_web_user_set_nickname      (PicasaWebUser *self,
+						     const char    *value);
+void              picasa_web_user_set_icon          (PicasaWebUser *self,
+						     const char    *value);
+void              picasa_web_user_set_quota_limit   (PicasaWebUser *self,
+						     const char    *value);
+void              picasa_web_user_set_quota_current (PicasaWebUser *self,
+						     const char    *value);
+void              picasa_web_user_set_max_photos    (PicasaWebUser *self,
+						     const char    *value);
+
+G_END_DECLS
+
+#endif /* PICASA_WEB_USER_H */



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