[f-spot: 1/3] From 7bbf4f3a8d87b7cb72cdb4153ace6b9487ab4acf Mon Sep 17 00:00:00 2001



commit 80d6cca1b02f176a6c6d6e4e2613ac2f975fbdc4
Author: Lorenzo Milesi <maxxer yetopen it>
Date:   Tue Jun 9 13:34:00 2009 +0200

    From 7bbf4f3a8d87b7cb72cdb4153ace6b9487ab4acf Mon Sep 17 00:00:00 2001
    From: =?utf-8?q?Wojciech=20Dzier=C5=BCanowski?=
    <wojciech dzierzanowski gmail com>
    Date: Mon, 11 May 2009 23:09:31 +0200
    Subject: [PATCH] TabbloExport refactorings and bugfixes
    
       * `Mono.Tabblo' namespace now uses `System.Diagnostics' for logging.
         `Mono.Tabblo' must not depend on F-Spot.  When `Mono.Tabblo' runs
    within
         F-Spot, its diagnostic output still goes through `FSpot.Utils.Log'
    thanks
         to a listener attached by `TabbloExport' to
    `System.Diagnostics.Debug'.
       * `FSpotTabbloExport' namespace adopted an MVC design.
       * Some other minor refactorings.
       * Fixed bug: The "Export" button should have the initial input focus.
       * Fixed bug: Work around tabblo.com's  way of determining the
       * expected
         image file format.  tabblo.com expects the file type to match the
         file extension specified as one of the POST arguments.
    TabbloExport
         used to set this argument to the name of the original file rather
    than
         the version actually being exported.  This caused trouble e.g. when
         exporting photos developed from RAW with DevelopInUFRaw.
       * Bumped version number.
---
 .../ApplicationCentricCertificatePolicy.cs         |   14 +-
 extensions/Exporters/TabbloExport/AssemblyInfo.cs  |    2 +-
 .../TabbloExport/BlindTrustCertificatePolicy.cs    |    4 +-
 extensions/Exporters/TabbloExport/Makefile.am      |    4 +-
 extensions/Exporters/TabbloExport/Preferences.cs   |   63 ----
 .../Exporters/TabbloExport/Tabblo/AssemblyInfo.cs  |    2 +-
 .../Exporters/TabbloExport/Tabblo/Connection.cs    |  155 +++++++----
 .../Exporters/TabbloExport/Tabblo/Makefile.am      |    5 +-
 .../TabbloExport/Tabblo/MultipartRequest.cs        |   10 +-
 .../Exporters/TabbloExport/Tabblo/Picture.cs       |   68 +++--
 .../TabbloExport/Tabblo/TotalUploadProgress.cs     |   10 +-
 .../Exporters/TabbloExport/TabbloExport.addin.xml  |    4 +-
 extensions/Exporters/TabbloExport/TabbloExport.cs  |  303 +++++++++----------
 .../Exporters/TabbloExport/TabbloExport.glade      |    9 +-
 .../TabbloExport/UserDecisionCertificatePolicy.cs  |    2 +-
 15 files changed, 309 insertions(+), 346 deletions(-)

diff --git a/extensions/Exporters/TabbloExport/ApplicationCentricCertificatePolicy.cs b/extensions/Exporters/TabbloExport/ApplicationCentricCertificatePolicy.cs
index 7ffd85a..6a320c3 100644
--- a/extensions/Exporters/TabbloExport/ApplicationCentricCertificatePolicy.cs
+++ b/extensions/Exporters/TabbloExport/ApplicationCentricCertificatePolicy.cs
@@ -4,7 +4,7 @@
 // Authors:
 //	Wojciech Dzierzanowski (wojciech dzierzanowski gmail com)
 //
-// (C) Copyright 2008 Wojciech Dzierzanowski
+// (C) Copyright 2009 Wojciech Dzierzanowski
 //
 
 // Permission is hereby granted, free of charge, to any person obtaining
@@ -62,7 +62,9 @@ namespace FSpotTabbloExport {
 		                                   WebRequest request,
 						   int problem)
 		{
-			Log.DebugFormat ("Checking validation result for {0}: problem={1}", request.RequestUri, problem);
+			Log.DebugFormat ("Checking validation result for {0}: "
+					+ "problem={1}",
+					request.RequestUri, problem);
 
 			if (0 == problem) {
 				return true;
@@ -77,17 +79,17 @@ namespace FSpotTabbloExport {
 			LoadCertificates ();
 
 			string hash = certificate.GetCertHashString ();
-			Log.DebugFormat ("Certificate hash: " + hash);
+			Log.Debug ("Certificate hash: " + hash);
 
 			int stored_problem = 0;
 			if (cert_hashes.TryGetValue (hash, out stored_problem)
 					&& problem == stored_problem) {
-				Log.DebugFormat ("We already trust this site");
+				Log.Debug ("We already trust this site");
 				return true;
 			}
 
 			Decision decision = GetDecision (certificate, request);
-			Log.DebugFormat ("Decision: " + decision);
+			Log.Debug ("Decision: " + decision);
 
 			switch (decision) {
 			case Decision.DontTrust:
@@ -109,7 +111,7 @@ namespace FSpotTabbloExport {
 				WebRequest request)
 		{
 			Decision decision = Decision.DontTrust;
-			Log.DebugFormat ("Making the default decision: " + decision);
+			Log.Debug ("Making the default decision: " + decision);
 			return decision;
 		}
 
diff --git a/extensions/Exporters/TabbloExport/AssemblyInfo.cs b/extensions/Exporters/TabbloExport/AssemblyInfo.cs
index 21fd49b..7da6049 100644
--- a/extensions/Exporters/TabbloExport/AssemblyInfo.cs
+++ b/extensions/Exporters/TabbloExport/AssemblyInfo.cs
@@ -29,4 +29,4 @@ using System.Runtime.InteropServices;
 //
 // You can specify all the values or you can use the default the Revision and
 // Build Numbers by using the '*' as shown below:
-[assembly: AssemblyVersion ("0.1.*")]
+[assembly: AssemblyVersion ("0.2.*")]
diff --git a/extensions/Exporters/TabbloExport/BlindTrustCertificatePolicy.cs b/extensions/Exporters/TabbloExport/BlindTrustCertificatePolicy.cs
index 248e54e..cfe157e 100644
--- a/extensions/Exporters/TabbloExport/BlindTrustCertificatePolicy.cs
+++ b/extensions/Exporters/TabbloExport/BlindTrustCertificatePolicy.cs
@@ -4,7 +4,7 @@
 // Authors:
 //	Wojciech Dzierzanowski (wojciech dzierzanowski gmail com)
 //
-// (C) Copyright 2008 Wojciech Dzierzanowski
+// (C) Copyright 2009 Wojciech Dzierzanowski
 //
 
 // Permission is hereby granted, free of charge, to any person obtaining
@@ -39,7 +39,7 @@ namespace FSpotTabbloExport {
 		                                   WebRequest request,
 						   int problem)
 		{
-			Log.DebugFormat ("Blindly trusting " + request.RequestUri);
+			Log.Warning ("Blindly trusting " + request.RequestUri);
 			return true;
 		}
 	}
diff --git a/extensions/Exporters/TabbloExport/Makefile.am b/extensions/Exporters/TabbloExport/Makefile.am
index a5d111b..fc949d2 100644
--- a/extensions/Exporters/TabbloExport/Makefile.am
+++ b/extensions/Exporters/TabbloExport/Makefile.am
@@ -10,9 +10,11 @@ PLUGIN_SOURCES = \
 	$(srcdir)/ApplicationCentricCertificatePolicy.cs \
 	$(srcdir)/AssemblyInfo.cs \
 	$(srcdir)/BlindTrustCertificatePolicy.cs \
+	$(srcdir)/FSpotTraceListener.cs \
 	$(srcdir)/FSpotUploadProgress.cs \
-	$(srcdir)/Preferences.cs \
 	$(srcdir)/TabbloExport.cs \
+	$(srcdir)/TabbloExportModel.cs \
+	$(srcdir)/TabbloExportView.cs \
 	$(srcdir)/UserDecisionCertificatePolicy.cs
 
 
diff --git a/extensions/Exporters/TabbloExport/Preferences.cs b/extensions/Exporters/TabbloExport/Preferences.cs
deleted file mode 100644
index 485e28f..0000000
--- a/extensions/Exporters/TabbloExport/Preferences.cs
+++ /dev/null
@@ -1,63 +0,0 @@
-//
-// FSpotTabbloExport.Preferences
-//
-// Authors:
-//	Wojciech Dzierzanowski (wojciech dzierzanowski gmail com)
-//
-// (C) Copyright 2008 Wojciech Dzierzanowski
-//
-
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-
-using System;
-
-namespace FSpotTabbloExport {
-
-	class Preferences : Mono.Tabblo.IPreferences {
-
-		private string username;
-		private string password;
-
-		public string Username {
-			get {
-				return username;
-			}
-		}
-		public string Password {
-			get {
-				return password;
-			}
-		}
-		public string Privacy {
-			get {
-				return "circle";
-			}
-		}
-
-		internal void SetUsername (string username) {
-			this.username = username;
-		}
-
-		internal void SetPassword (string password) {
-			this.password = password;
-		}
-	}
-}
diff --git a/extensions/Exporters/TabbloExport/Tabblo/AssemblyInfo.cs b/extensions/Exporters/TabbloExport/Tabblo/AssemblyInfo.cs
index 5aebc06..977e76e 100644
--- a/extensions/Exporters/TabbloExport/Tabblo/AssemblyInfo.cs
+++ b/extensions/Exporters/TabbloExport/Tabblo/AssemblyInfo.cs
@@ -29,4 +29,4 @@ using System.Runtime.InteropServices;
 //
 // You can specify all the values or you can use the default the Revision and
 // Build Numbers by using the '*' as shown below:
-[assembly: AssemblyVersion ("0.1.*")]
+[assembly: AssemblyVersion ("0.2.*")]
diff --git a/extensions/Exporters/TabbloExport/Tabblo/Connection.cs b/extensions/Exporters/TabbloExport/Tabblo/Connection.cs
index ce1a178..067bf22 100644
--- a/extensions/Exporters/TabbloExport/Tabblo/Connection.cs
+++ b/extensions/Exporters/TabbloExport/Tabblo/Connection.cs
@@ -4,7 +4,7 @@
 // Authors:
 //	Wojciech Dzierzanowski (wojciech dzierzanowski gmail com)
 //
-// (C) Copyright 2008 Wojciech Dzierzanowski
+// (C) Copyright 2009 Wojciech Dzierzanowski
 //
 
 // Permission is hereby granted, free of charge, to any person obtaining
@@ -34,12 +34,11 @@ using System.Diagnostics;
 using System.IO;
 using System.Net;
 using System.Text;
-
-using FSpot.Utils;
+using System.Web;
 
 namespace Mono.Tabblo {
 
-	public class Connection {
+	class Connection {
 
 		private const string LoginUrl =
 				"https://store.tabblo.com:443/studio/authtoken";;
@@ -49,6 +48,10 @@ namespace Mono.Tabblo {
 				+ "/token/{0}/?url=/studio"
 				+ "/report_upload_session";
 
+		private const string ContentTypeUrlEncoded =
+				"application/x-www-form-urlencoded; "
+				+ "charset=UTF-8";
+
 		private readonly IPreferences preferences;
 
 		private string auth_token = null;
@@ -57,24 +60,24 @@ namespace Mono.Tabblo {
 		private CookieCollection cookies;
 
 
-		public Connection (IPreferences preferences)
+		internal Connection (IPreferences preferences)
 		{
-			if (null == preferences) {
-				throw new ArgumentNullException ("preferences");
-			}
+			Debug.Assert (null != preferences);
 			this.preferences = preferences;
 			this.cookies = new CookieCollection ();
 		}
 
 
-		public void UploadFile (string name, Stream data_stream,
-		                        string mime_type, string [,] arguments)
+		internal void UploadFile (string name, Stream data_stream,
+		                          string mime_type,
+		                          string [,] arguments)
 		{
 			if (!IsAuthenticated ()) {
 				Login ();
 			}
 
-			Log.DebugFormat ("Uploading " + mime_type + " file " + name);
+			Debug.WriteLine ("Uploading " + mime_type + " file "
+					+ name);
 			DoUploadFile (name, data_stream, mime_type, arguments);
 		}
 
@@ -90,7 +93,7 @@ namespace Mono.Tabblo {
 					new MultipartRequest (http_request);
 
 			MemoryStream mem_stream = null;
-			if (null != UploadProgressHandler) {
+			if (null != UploadProgressChanged) {
 				// "Manual buffering" using a MemoryStream.
 				request.Request.AllowWriteStreamBuffering =
 						false;
@@ -102,6 +105,9 @@ namespace Mono.Tabblo {
 			request.AddHeader ("Content-Disposition",
 					"form-data; name=\"filename0\"; "
 							+ "filename=\"" + name
+							+ GetFileNameExtension (
+								mime_type)
+
 							+ '"',
 					false);
 			request.AddHeader ("Content-Type", mime_type, true);
@@ -117,7 +123,7 @@ namespace Mono.Tabblo {
 			request.EndPartialContent ();
 			request.EndPart (true);
 
-			if (null != UploadProgressHandler) {
+			if (null != UploadProgressChanged) {
 
 				int total = (int) request.OutputStream.Length;
 				request.Request.ContentLength = total;
@@ -154,17 +160,36 @@ namespace Mono.Tabblo {
 		}
 
 
-		public event UploadProgressEventHandler UploadProgressHandler;
+		private static string GetFileNameExtension(string mime_type)
+		{
+			switch (mime_type)
+			{
+				case "image/jpeg":
+					return ".jpeg";
+
+				case "image/png":
+					return ".png";
+
+				default:
+					Debug.WriteLine (
+							"Unexpected MIME type: "
+							+ mime_type);
+					return ".jpeg";
+			}
+		}
+
+
+		internal event UploadProgressEventHandler UploadProgressChanged;
 
 		private void FireUploadProgress (string title, int sent,
 		                                 int total)
 		{
-			if (null != UploadProgressHandler) {
+			if (null != UploadProgressChanged) {
 				UploadProgressEventArgs args =
 						new UploadProgressEventArgs (
 								title, sent,
 								total);
-				UploadProgressHandler (this, args);
+				UploadProgressChanged (this, args);
 			}
 		}
 
@@ -185,8 +210,7 @@ namespace Mono.Tabblo {
 
 			HttpWebRequest request = CreateHttpRequest (
 					LoginUrl, "POST");
-			request.ContentType =
-					"application/x-www-form-urlencoded";
+			request.ContentType = ContentTypeUrlEncoded;
 
 			string [,] arguments = {
 				{"username", preferences.Username},
@@ -194,13 +218,12 @@ namespace Mono.Tabblo {
 			};
 
 			try {
-				WriteRequestContent (request,
-						FormatRequestArguments (
-								arguments));
+				WriteRequestContent (request, arguments);
 				string response = SendRequest (
 						"login", request);
 				if ("BAD".Equals (response)) {
-					Log.DebugFormat ("Invalid username or password");
+					Debug.WriteLine (
+						"Invalid username or password");
 					throw new TabbloException (
 						"Login failed: Invalid username"
 						+ " or password");
@@ -219,19 +242,22 @@ namespace Mono.Tabblo {
 				// `GetUploadUrl()'.
 				WebException we = e.InnerException
 						as WebException;
-				if (null != we)
-					Log.DebugFormat ("Caught a WebException, status=" + we.Status);
-				if (null != we
-					&& WebExceptionStatus.TrustFailure
+				if (null != we) {
+					Debug.WriteLine ("Caught a WebException,"
+							+ " status="
+							+ we.Status);
+					if (WebExceptionStatus.TrustFailure
 							== we.Status) {
-					throw new TabbloException (
+						throw new TabbloException (
 							"Trust failure", we);
+					}
 				}
 				throw;
 			}
 
-			if  (null != auth_token)
-				Log.DebugFormat  ("Login successful. Token: " + auth_token);
+			Debug.WriteLineIf (null != auth_token,
+					"Login successful. Token: "
+					+ auth_token);
 		}
 
 
@@ -241,13 +267,13 @@ namespace Mono.Tabblo {
 						"Obtaining URL for upload"),
 					0, 0);
 
-			if (! IsAuthenticated ())
-				Log.DebugFormat ("Not authenticated");
+			Debug.Assert (IsAuthenticated (), "Not authenticated");
 
 			if (null == session_upload_url) {
 
-				string [,] auth_arguments =
-						{ {"auth_token", auth_token} };
+				string [,] auth_arguments = {
+					{"auth_token", auth_token}
+				};
 				string url = AuthorizeUrl + "/?"
 						+ FormatRequestArguments (
 								auth_arguments);
@@ -276,7 +302,7 @@ namespace Mono.Tabblo {
 						arguments);
 			}
 
-			Log.DebugFormat ("Upload URL: " + upload_url);
+			Debug.WriteLine ("Upload URL: " + upload_url);
 			return upload_url;
 		}
 
@@ -320,12 +346,19 @@ namespace Mono.Tabblo {
 
 			string cookie_header = request.CookieContainer
 					.GetCookieHeader (request.RequestUri);
-			if (cookie_header.Length > 0)
-				Log.DebugFormat ("Cookie: " + cookie_header);
+			Debug.WriteLineIf (cookie_header.Length > 0,
+					"Cookie: " + cookie_header);
 		}
 
 
 		private static void WriteRequestContent (HttpWebRequest request,
+		                                         string [,] arguments)
+		{
+			WriteRequestContent (request,
+					FormatRequestArguments (arguments));
+		}
+
+		private static void WriteRequestContent (HttpWebRequest request,
 		                                         string content)
 		{
 			byte [] content_bytes =
@@ -340,7 +373,9 @@ namespace Mono.Tabblo {
 							content_bytes.Length);
 				}
 			} catch (WebException e) {
-				Log.Exception (e);
+				Debug.WriteLine (
+						"Error writing request content",
+						"ERROR");
 				throw new TabbloException (
 						"HTTP request failure: "
 								+ e.Message,
@@ -349,7 +384,8 @@ namespace Mono.Tabblo {
 
 			char [] content_chars = new char [content_bytes.Length];
 			content_bytes.CopyTo (content_chars, 0);
-			Log.DebugFormat ("Request content: " + new string (content_chars));
+			Debug.WriteLine ("Request content: "
+					+ new string (content_chars));
 		}
 
 
@@ -360,20 +396,17 @@ namespace Mono.Tabblo {
 
 			for (int i = 0; i < arguments.GetLength (0); ++i) {
 				content.AppendFormat( "{0}={1}&",
-						arguments [i, 0],
-						arguments [i, 1]);
+						HttpUtility.UrlEncode (
+							arguments [i, 0]),
+						HttpUtility.UrlEncode (
+							arguments [i, 1]));
 			}
 
 			if (content.Length > 0) {
 				content.Remove (content.Length - 1, 1);
 			}
 
-			byte [] content_bytes =	Encoding.UTF8.GetBytes (
-					content.ToString ());
-			char [] content_chars = new char [content_bytes.Length];
-			content_bytes.CopyTo (content_chars, 0);
-
-			return new string (content_chars);
+			return content.ToString ();
 		}
 
 
@@ -393,7 +426,9 @@ namespace Mono.Tabblo {
 		                            HttpWebRequest request,
 		                            bool keep_cookies)
 		{
-			Log.DebugFormat ("Sending " + description + ' ' + request.Method + " request to " + request.Address);
+			Debug.WriteLine ("Sending " + description + ' '
+					+ request.Method + " request to "
+					+ request.Address);
 
 			HttpWebResponse response = null;
 			try {
@@ -401,14 +436,21 @@ namespace Mono.Tabblo {
 						request.GetResponse ();
 				if (keep_cookies) {
 					cookies.Add (response.Cookies);
-					Log.DebugFormat (response.Cookies.Count + " cookie(s)");
+					Debug.WriteLine (response.Cookies.Count
+							+ " cookie(s)");
 					foreach (Cookie c in response.Cookies) {
-						Log.DebugFormat ("Set-Cookie: " + c.Name + '=' + c.Value + "; Domain=" + c.Domain + "; expires=" + c.Expires);
+						Debug.WriteLine ("Set-Cookie: "
+								+ c.Name + '='
+								+ c.Value
+								+ "; Domain="
+								+ c.Domain
+								+ "; expires="
+								+ c.Expires);
 					}
 				}
 				return GetResponseAsString (response);
 			} catch (WebException e) {
-				Log.Exception (e);
+				Debug.WriteLine (description + " failed: " + e);
 				HttpWebResponse error_response =
 						e.Response as HttpWebResponse;
 				string response_string = null != error_response
@@ -427,9 +469,10 @@ namespace Mono.Tabblo {
 		}
 
 
-		private static string GetResponseAsString (HttpWebResponse response)
+		private static string GetResponseAsString (
+				HttpWebResponse response)
 		{
-			Log.DebugFormat ("Response: ");
+			Debug.Write ("Response: ");
 
 			Encoding encoding = Encoding.UTF8;
 			if (response.ContentEncoding.Length > 0) {
@@ -452,12 +495,8 @@ namespace Mono.Tabblo {
 				stream.Close ();
 			}
 
-			if (null != response_string)
-				try {
-					Log.DebugFormat (response_string);
-				} catch (System.FormatException e) {
-					Log.DebugFormat ("Unable to print respose string: not in correct format");
-				}
+			Debug.WriteLineIf (null != response_string,
+					response_string);
 			return response_string;
 		}
 	}
diff --git a/extensions/Exporters/TabbloExport/Tabblo/Makefile.am b/extensions/Exporters/TabbloExport/Tabblo/Makefile.am
index 3d32421..822253c 100644
--- a/extensions/Exporters/TabbloExport/Tabblo/Makefile.am
+++ b/extensions/Exporters/TabbloExport/Tabblo/Makefile.am
@@ -10,12 +10,13 @@ ASSEMBLY_SOURCES = \
 	$(srcdir)/Picture.cs \
 	$(srcdir)/TabbloException.cs \
 	$(srcdir)/TotalUploadProgress.cs \
+	$(srcdir)/Uploader.cs \
 	$(srcdir)/UploadProgressEventArgs.cs \
 	$(srcdir)/UploadProgressEventHandler.cs
 
 REFS = \
-       -r:$(top_builddir)/src/FSpot.Utils.dll \
-       -r:Mono.Posix.dll
+       -r:Mono.Posix.dll \
+       -r:System.Web.dll
 
 PKGS =
 
diff --git a/extensions/Exporters/TabbloExport/Tabblo/MultipartRequest.cs b/extensions/Exporters/TabbloExport/Tabblo/MultipartRequest.cs
index 08a902f..a626f5a 100644
--- a/extensions/Exporters/TabbloExport/Tabblo/MultipartRequest.cs
+++ b/extensions/Exporters/TabbloExport/Tabblo/MultipartRequest.cs
@@ -8,7 +8,7 @@
 //
 // (C) Copyright 2006 Novell, Inc. (http://www.novell.com)
 // (C) Copyright 2007 S. Delcroix
-// (C) Copyright 2008 Wojciech Dzierzanowski
+// (C) Copyright 2009 Wojciech Dzierzanowski
 //
 
 // Permission is hereby granted, free of charge, to any person obtaining
@@ -39,8 +39,6 @@ using System.IO;
 using System.Net;
 using System.Text;
 
-using FSpot.Utils;
-
 namespace Mono.Tabblo {
 
 	class MultipartRequest {
@@ -202,13 +200,13 @@ namespace Mono.Tabblo {
 		[Conditional (VerboseSymbol)]
 		private static void LogBeginPart ()
 		{
-			Log.DebugFormat (">>>START MultipartRequest content");
+			Debug.WriteLine (">>>START MultipartRequest content");
 		}
 
 		[Conditional (VerboseSymbol)]
 		private static void LogEndPart ()
 		{
-			Log.DebugFormat ("<<<END MultipartRequest content");
+			Debug.WriteLine ("<<<END MultipartRequest content");
 		}
 
 		[Conditional (VerboseSymbol)]
@@ -217,7 +215,7 @@ namespace Mono.Tabblo {
 		{
 			char [] content_chars = new char [length];
 			Array.Copy (content, offset, content_chars, 0, length);
-			Log.DebugFormat (new string (content_chars));
+			Debug.Write (new string (content_chars));
 		}
 	}
 }
diff --git a/extensions/Exporters/TabbloExport/Tabblo/Picture.cs b/extensions/Exporters/TabbloExport/Tabblo/Picture.cs
index a1bc654..6b23e74 100644
--- a/extensions/Exporters/TabbloExport/Tabblo/Picture.cs
+++ b/extensions/Exporters/TabbloExport/Tabblo/Picture.cs
@@ -4,7 +4,7 @@
 // Authors:
 //	Wojciech Dzierzanowski (wojciech dzierzanowski gmail com)
 //
-// (C) Copyright 2008 Wojciech Dzierzanowski
+// (C) Copyright 2009 Wojciech Dzierzanowski
 //
 
 // Permission is hereby granted, free of charge, to any person obtaining
@@ -28,7 +28,7 @@
 //
 
 using System;
-using System.IO;
+using System.Collections.Generic;
 
 namespace Mono.Tabblo {
 
@@ -39,6 +39,30 @@ namespace Mono.Tabblo {
 		private readonly string mime_type;
 		private readonly string privacy;
 
+		private List<string> tags = new List<string> ();
+ 
+		
+		public Picture (string name, Uri uri, string mime_type,
+		                string privacy)
+		{
+			if (null == name) {
+				throw new ArgumentNullException ("name");
+			}
+			if (null == uri) {
+				throw new ArgumentNullException ("uri");
+			}
+			if (null == mime_type) {
+				throw new ArgumentNullException ("mime_type");
+			}
+			if (null == privacy) {
+				throw new ArgumentNullException ("privacy");
+			}
+			this.name = name;
+			this.uri = uri;
+			this.mime_type = mime_type;
+			this.privacy = privacy;
+		}
+
 
 		public string Name {
 			get {
@@ -60,41 +84,21 @@ namespace Mono.Tabblo {
 				return privacy;
 			}
 		}
-
-
-		public Picture (string name, Uri uri, string mime_type,
-		                string privacy)
-		{
-			if (null == name) {
-				throw new ArgumentNullException ("name");
-			}
-			if (null == uri) {
-				throw new ArgumentNullException ("uri");
-			}
-			if (null == mime_type) {
-				throw new ArgumentNullException ("mime_type");
-			}
-			if (null == privacy) {
-				throw new ArgumentNullException ("privacy");
+		public string[] Tags {
+			get {
+				return tags.ToArray ();
 			}
-			this.name = name;
-			this.uri = uri;
-			this.mime_type = mime_type;
-			this.privacy = privacy;
 		}
 
 
-		public void Upload (Connection connection)
+		public void AddTag (string tag)
 		{
-			if (null == connection) {
-				throw new ArgumentNullException ("connection");
-			}
-
-			using (Stream data_stream =
-					File.OpenRead (Uri.LocalPath)) {
-				connection.UploadFile (Name, data_stream,
-						MimeType, null);
-			}
+			if (null == tag) {
+				throw new ArgumentNullException ("tag");
+ 			}
+			if (!tags.Contains (tag)) {
+				tags.Add (tag);
+ 			}
 		}
 	}
 }
diff --git a/extensions/Exporters/TabbloExport/Tabblo/TotalUploadProgress.cs b/extensions/Exporters/TabbloExport/Tabblo/TotalUploadProgress.cs
index 4cd2f3e..87bcc2f 100644
--- a/extensions/Exporters/TabbloExport/Tabblo/TotalUploadProgress.cs
+++ b/extensions/Exporters/TabbloExport/Tabblo/TotalUploadProgress.cs
@@ -4,7 +4,7 @@
 // Authors:
 //	Wojciech Dzierzanowski (wojciech dzierzanowski gmail com)
 //
-// (C) Copyright 2008 Wojciech Dzierzanowski
+// (C) Copyright 2009 Wojciech Dzierzanowski
 //
 
 // Permission is hereby granted, free of charge, to any person obtaining
@@ -31,8 +31,6 @@ using System;
 using System.IO;
 using System.Diagnostics;
 
-using FSpot.Utils;
-
 namespace Mono.Tabblo {
 
 	public class TotalUploadProgress {
@@ -46,7 +44,7 @@ namespace Mono.Tabblo {
 
 		public TotalUploadProgress (Picture [] pictures)
 		{
-			if (null == pictures) Log.DebugFormat ("No pictures!");
+			Debug.Assert (null != pictures, "No pictures!");
 
 			total_file_count = pictures.Length;
 			total_file_size = GetTotalFileSize (pictures);
@@ -74,7 +72,7 @@ namespace Mono.Tabblo {
 			int percent = (int)
 					((double) bytes_sent_total * 100
 							/ TotalFileSize);
-			Log.DebugFormat ("{0}%...", percent);
+			Debug.Write (String.Format ("{0}%...", percent));
 
 			if (args.BytesTotal == args.BytesSent) {
 				prev_bytes_sent = 0;
@@ -98,7 +96,7 @@ namespace Mono.Tabblo {
 
 		private static ulong GetTotalFileSize (Picture [] pictures)
 		{
-			if (null == pictures) Log.DebugFormat ("No pictures!");
+			Debug.Assert (null != pictures, "No pictures!");
 
 			ulong size = 0;
 
diff --git a/extensions/Exporters/TabbloExport/TabbloExport.addin.xml b/extensions/Exporters/TabbloExport/TabbloExport.addin.xml
index 6b953d8..5ef56b6 100644
--- a/extensions/Exporters/TabbloExport/TabbloExport.addin.xml
+++ b/extensions/Exporters/TabbloExport/TabbloExport.addin.xml
@@ -1,8 +1,8 @@
 <Addin namespace="FSpot"
-	version="0.6"
+	version="0.6.0.1"
 	name="Tabblo Export"
 	description="This extension allows you to export your photos to Tabblo."
-	author="Wojciech Dzierzanowski"
+ 	author="Wojciech Dzierżanowski"
 	defaultEnabled="false"
 	category="Export">
 
diff --git a/extensions/Exporters/TabbloExport/TabbloExport.cs b/extensions/Exporters/TabbloExport/TabbloExport.cs
index 704f3ec..015876f 100644
--- a/extensions/Exporters/TabbloExport/TabbloExport.cs
+++ b/extensions/Exporters/TabbloExport/TabbloExport.cs
@@ -4,7 +4,7 @@
 // Authors:
 //	Wojciech Dzierzanowski (wojciech dzierzanowski gmail com)
 //
-// (C) Copyright 2008 Wojciech Dzierzanowski
+// (C) Copyright 2009 Wojciech Dzierzanowski
 //
 
 // Permission is hereby granted, free of charge, to any person obtaining
@@ -40,246 +40,231 @@ using FSpot.Utils;
 using FSpot.UI.Dialog;
 
 namespace FSpotTabbloExport {
-	/// <summary>
-	/// </summary>
-	public class TabbloExport : FSpot.Extensions.IExporter {
-
-		private readonly Preferences preferences;
-		private readonly Connection connection;
 
-		private FSpot.IBrowsableCollection photos;
+	public class TabbloExport : FSpot.Extensions.IExporter {
 
-		private const string DialogName = "tabblo_export_dialog";
-		[Glade.Widget] Gtk.Dialog dialog;
-		[Glade.Widget] Gtk.Entry username_entry;
-		[Glade.Widget] Gtk.Entry password_entry;
-		[Glade.Widget] Gtk.Button export_button;
-		[Glade.Widget] Gtk.Button cancel_button;
-		[Glade.Widget] Gtk.ScrolledWindow thumb_scrolled_window;
+		private readonly TabbloExportModel model;
 
+		private TabbloExportView main_dialog;
 		private ThreadProgressDialog progress_dialog;
 
-		// Keyring constants.
-		private const string KeyringItemName = "Tabblo Account";
-		private const string KeyringItemApp = "FSpotTabbloExport";
-		private const string KeyringItemNameAttr = "name";
-		private const string KeyringItemUsernameAttr = "username";
-		private const string KeyringItemAppAttr = "application";
+		private readonly Uploader uploader;
+		private TraceListener debug_listener;
+		private TotalUploadProgress upload_progress;
+
 
+		//
+		// Initialization
+		//
 
 		public TabbloExport ()
 		{
-			preferences = new Preferences ();
-			connection = new Connection (preferences);
+			model = new TabbloExportModel ();
+			uploader = new Uploader (model);
 		}
 
 
 		public void Run (FSpot.IBrowsableCollection photos)
 		{
-			if (null == photos) {
+			if (null == photos || null == photos.Items) {
 				throw new ArgumentNullException ("photos");
 			}
 
-			this.photos = photos;
+			main_dialog = new TabbloExportView (photos);
 
-			Glade.XML glade_xml = new Glade.XML (
-					null, "TabbloExport.glade", DialogName,
-					"f-spot");
-			glade_xml.Autoconnect (this);
+			InitBindings ();
 
-			dialog = (Gtk.Dialog) glade_xml.GetWidget (DialogName);
+			model.Deserialize ();
+			model.PhotoCollection = photos;
+
+			// Model deserialization triggers the various event
+			// handlers, which can cause the default widget to lose
+			// focus (it can be invalid, and hence disabled, for a
+			// moment).
+			main_dialog.ResetFocus ();
+		}
 
-			FSpot.Widgets.IconView icon_view =
-					new FSpot.Widgets.IconView (photos);
-			icon_view.DisplayDates = false;
-			icon_view.DisplayTags = false;
 
-			username_entry.Changed += HandleAccountDataChanged;
-			password_entry.Changed += HandleAccountDataChanged;
-			ReadAccountData ();
-			HandleAccountDataChanged (null, null);
+		private void InitBindings ()
+		{
+			Debug.Assert (null != model);
+			Debug.Assert (null != main_dialog);
 
-			dialog.Modal = false;
-			dialog.TransientFor = null;
+			main_dialog.tabblo_export_dialog.Response +=
+					HandleResponse;
 
-			dialog.Response += HandleResponse;
+			// Account data
+			model.UsernameChanged += HandleUsernameChanged;
+			main_dialog.username_entry.Changed +=
+					HandleUsernameChanged;
 
-			thumb_scrolled_window.Add (icon_view);
-			icon_view.Show ();
-			dialog.Show ();
+			model.PasswordChanged += HandlePasswordChanged;
+			main_dialog.password_entry.Changed +=
+					HandlePasswordChanged;
 		}
 
 
-		private void HandleAccountDataChanged (object sender,
-		                                       EventArgs args)
+		//
+		// Event handlers
+		//
+
+		private void HandleUsernameChanged (object sender,
+		                                    EventArgs args)
 		{
-			preferences.SetUsername (username_entry.Text);
-			preferences.SetPassword (password_entry.Text);
+			if (model == sender) {
+				main_dialog.username_entry.Text = model.Username;
+				OnAccountDataChanged ();
+			} else {
+				model.Username = main_dialog.username_entry.Text;
+			}
+		}
+
+		private void HandlePasswordChanged (object sender,
+		                                    EventArgs args)
+		{
+			if (model == sender) {
+				main_dialog.password_entry.Text = model.Password;
+				OnAccountDataChanged ();
+			} else {
+				model.Password = main_dialog.password_entry.Text;
+			}
+		}
 
-			export_button.Sensitive =
-					preferences.Username.Length > 0
-					&& preferences.Password.Length > 0;
+		private void OnAccountDataChanged ()
+		{
+			main_dialog.Validated =
+					model.Username.Length > 0
+					&& model.Password.Length > 0;
 		}
 
 
 		private void HandleResponse (object sender,
 		                             Gtk.ResponseArgs args)
 		{
-			dialog.Destroy ();
+			main_dialog.Destroy ();
 
 			if (Gtk.ResponseType.Ok != args.ResponseId) {
-				Log.DebugFormat ("Tabblo export was canceled.");
+				Log.Information ("Tabblo export was canceled.");
 				return;
 			}
-
-			WriteAccountData ();
-
-			Log.DebugFormat ("Starting Tabblo export");
-
+			
+			model.Serialize ();
+			
+			Log.Information ("Starting Tabblo export");
+			
 			Thread upload_thread =
 					new Thread (new ThreadStart (Upload));
 			progress_dialog = new ThreadProgressDialog (
-					upload_thread, photos.Items.Length);
+					upload_thread, model.Photos.Length);
 			progress_dialog.Start ();
 		}
-
+		
+		
+		//
+		// Upload logic
+		// 
 
 		private void Upload ()
 		{
-			if (null == connection) Log.DebugFormat ("No connection");
-
-			Picture [] pictures = GetPicturesForUpload ();
-
-			FSpotUploadProgress fup = new FSpotUploadProgress (
-					pictures, progress_dialog);
-			connection.UploadProgressHandler += fup.HandleProgress;
-
-			ServicePointManager.CertificatePolicy =
-					new UserDecisionCertificatePolicy ();
+			Debug.Assert (null != uploader);
+			
+			Picture [] pictures = GetPicturesForUpload (); 
+			Debug.Assert (pictures.Length == model.Photos.Length);
 
+			OnUploadStarted (pictures);
+				
 			try {
-				foreach (Picture picture in pictures) {
-					picture.Upload (connection);
+				for (int i = 0; i < pictures.Length; ++i) {
+					uploader.Upload (pictures [i]);
+					OnPhotoUploaded (model.Photos [i]);
 				}
-
+				
 				progress_dialog.Message = Catalog.GetString (
 						"Done sending photos");
 				progress_dialog.ProgressText = Catalog
 						.GetString ("Upload complete");
 				progress_dialog.Fraction = 1;
 				progress_dialog.ButtonLabel = Gtk.Stock.Ok;
-
+				
 			} catch (TabbloException e) {
 				progress_dialog.Message = Catalog.GetString (
 						"Error uploading to Tabblo: ")
 						+ e.Message;
 				progress_dialog.ProgressText =
 						Catalog.GetString ("Error");
-				// FIXME:  Retry logic?
+				// FIXME:  Retry logic? 
 //				  progressDialog.PerformRetrySkip ();
-				Log.DebugFormat ("Error uploading:\n" + e);
+				Console.WriteLine (e);
 			} finally {
-				connection.UploadProgressHandler -=
-						fup.HandleProgress;
+				OnUploadFinished ();
 			}
 		}
+		
 
+		private void OnUploadStarted (Picture [] pictures)
+		{
+			Debug.Assert (null != pictures);
+			Debug.Assert (null != uploader);
+			Debug.Assert (null != progress_dialog);
+
+			// Initialize the debug output listener.
+			// `Mono.Tabblo' uses the standard
+			// `System.Diagnostics.Debug' facilities for debug
+			// output only.
+			debug_listener = new FSpotTraceListener ();
+			Debug.Listeners.Add (debug_listener);
+
+			// Initialize the progress handler.
+			upload_progress = new FSpotUploadProgress (
+					pictures, progress_dialog);
+			uploader.ProgressChanged +=
+					upload_progress.HandleProgress;
+			
+			// Set up the certificate policy.
+			ServicePointManager.CertificatePolicy =
+					new UserDecisionCertificatePolicy ();
+		}
 
-		private Picture [] GetPicturesForUpload ()
+		private void OnUploadFinished ()
 		{
-			if (null == photos) Log.DebugFormat ("No photos");
-			if (null == preferences) Log.DebugFormat ("No preferences");
+			Debug.Assert (null != uploader);
+			Debug.Assert (null != debug_listener);
+			Debug.Assert (null != upload_progress);
 
-			Picture [] pictures = new Picture [photos.Items.Length];
+			uploader.ProgressChanged -=
+					upload_progress.HandleProgress;
 
-			for (int i = 0; i < pictures.Length; ++i) {
-				FSpot.IBrowsableItem photo = photos.Items [i];
+			Debug.Listeners.Remove (debug_listener);
+		}
 
+		
+		private void OnPhotoUploaded (FSpot.IBrowsableItem item)
+		{
+			Debug.Assert (null != item);
+		}
+
+		
+		private Picture [] GetPicturesForUpload ()
+		{
+			Picture [] pictures = new Picture [model.Photos.Length];
+			FSpot.IBrowsableItem [] items = model.Photos;
+
+			for (int i = 0; i < pictures.Length; ++i) {
 				// FIXME: GnomeVFS is deprecated, we should use
 				// GIO instead.  However, I don't know how to
 				// call `GLib.Content.TypeGuess ()'.
-				string path = photo.DefaultVersionUri.LocalPath;
+				string path = items [i].DefaultVersionUri
+						.LocalPath;
 				string mime_type = Gnome.Vfs.MimeType
 						.GetMimeTypeForUri (path);
 
-				pictures [i] = new Picture (photo.Name,
-						photo.DefaultVersionUri,
+				pictures [i] = new Picture (items [i].Name,
+						items [i].DefaultVersionUri,
 						mime_type,
-						preferences.Privacy);
+						model.Privacy);
 			}
 
 			return pictures;
 		}
-
-
-		private void ReadAccountData ()
-		{
-			Hashtable attrs = new Hashtable ();
-			attrs [KeyringItemNameAttr] = KeyringItemName;
-			attrs [KeyringItemAppAttr] = KeyringItemApp;
-
-			try {
-				Gnome.Keyring.ItemType type = Gnome.Keyring
-						.ItemType.GenericSecret;
-				Gnome.Keyring.ItemData [] items =
-						Gnome.Keyring.Ring.Find (
-								type, attrs);
-				if (items.Length > 1)
-					Log.Warning ("More than one " + KeyringItemName + "found in keyring");
-
-				if (1 <= items.Length) {
-					Log.DebugFormat (KeyringItemName + " data found in " + "keyring");
-					attrs =	items [0].Attributes;
-					username_entry.Text = (string) attrs [
-						KeyringItemUsernameAttr];
-					password_entry.Text = items [0].Secret;
-				}
-
-			} catch (Gnome.Keyring.KeyringException e) {
-				Log.DebugFormat ("Error while reading account data:\n" + e);
-			}
-		}
-
-
-		private void WriteAccountData ()
-		{
-			try {
-				string keyring = Gnome.Keyring
-						.Ring.GetDefaultKeyring ();
-
-				Hashtable attrs = new Hashtable ();
-				attrs [KeyringItemNameAttr] = KeyringItemName;
-				attrs [KeyringItemAppAttr] = KeyringItemApp;
-
-				Gnome.Keyring.ItemType type = Gnome.Keyring
-						.ItemType.GenericSecret;
-
-				try {
-					Gnome.Keyring.ItemData [] items = Gnome
-							.Keyring.Ring.Find (
-									type,
-									attrs);
-
-					foreach (Gnome.Keyring.ItemData item
-							in items) {
-						Gnome.Keyring.Ring.DeleteItem (
-								keyring,
-								item.ItemID);
-					}
-				} catch (Gnome.Keyring.KeyringException e) {
-					Log.DebugFormat ("Error while deleting old account data:\n" + e);
-				}
-
-				attrs [KeyringItemUsernameAttr] =
-						preferences.Username;
-
-				Gnome.Keyring.Ring.CreateItem (keyring, type,
-						KeyringItemName, attrs,
-						preferences.Password, true);
-
-			} catch (Gnome.Keyring.KeyringException e) {
-				Log.DebugFormat ("Error while writing account data:\n" + e);
-			}
-		}
 	}
 }
diff --git a/extensions/Exporters/TabbloExport/TabbloExport.glade b/extensions/Exporters/TabbloExport/TabbloExport.glade
index 7c7830e..2ebfae8 100644
--- a/extensions/Exporters/TabbloExport/TabbloExport.glade
+++ b/extensions/Exporters/TabbloExport/TabbloExport.glade
@@ -29,7 +29,6 @@
                         <property name="width_request">180</property>
                         <property name="height_request">180</property>
                         <property name="visible">True</property>
-                        <property name="can_focus">True</property>
                         <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
                         <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
                         <property name="shadow_type">GTK_SHADOW_IN</property>
@@ -161,8 +160,9 @@
           <widget class="GtkHButtonBox" id="dialog-action_area11">
             <property name="visible">True</property>
             <property name="layout_style">GTK_BUTTONBOX_END</property>
+	    <property name="homogeneous">True</property>
             <child>
-              <widget class="GtkButton" id="cancelButton">
+              <widget class="GtkButton" id="cancel_button">
                 <property name="visible">True</property>
                 <property name="can_focus">True</property>
                 <property name="can_default">True</property>
@@ -175,14 +175,11 @@
               <widget class="GtkButton" id="export_button">
                 <property name="visible">True</property>
                 <property name="can_focus">True</property>
-                <property name="can_default">True</property>
+                <property name="has_focus">True</property>
                 <property name="label">_Export</property>
                 <property name="use_underline">True</property>
                 <property name="response_id">-5</property>
               </widget>
-              <packing>
-                <property name="position">1</property>
-              </packing>
             </child>
           </widget>
           <packing>
diff --git a/extensions/Exporters/TabbloExport/UserDecisionCertificatePolicy.cs b/extensions/Exporters/TabbloExport/UserDecisionCertificatePolicy.cs
index 91b1445..ccda10d 100644
--- a/extensions/Exporters/TabbloExport/UserDecisionCertificatePolicy.cs
+++ b/extensions/Exporters/TabbloExport/UserDecisionCertificatePolicy.cs
@@ -87,7 +87,7 @@ namespace FSpotTabbloExport {
 
 			Gtk.ResponseType response =
 					(Gtk.ResponseType) dialog.Run ();
-			Log.DebugFormat ("Decision dialog response: " + response);
+			Log.Debug ("Decision dialog response: " + response);
 
 			dialog.Destroy ();
 



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