Logo Search packages:      
Sourcecode: f-spot version File versions  Download package

SendEmail.cs

//
// SendEmail.cs: Lets user resize photos prior to sending them by mail. 
//
//    This function uses the following preferenses in gconf.
//          /apps/f-spot/export/email/size
//          /apps/f-spot/export/email/auto_rotate
//          /apps/f-spot/export/email/delete_timeout_seconds
//    
// Author:
//   Bengt Thuree (bengt@thuree.com)
//
// (C) 2006 Bengt Thuree
// 


using Gtk;
using Gnome;
using System;

namespace FSpot {
      public class SendEmail : FSpot.GladeDialog {
            PhotoQuery query;
            Gtk.Window parent_window;

            [Glade.Widget] private Button             ok_button;
            [Glade.Widget] private Label        NumberOfPictures, TotalOriginalSize, ApproxNewSize;   
            [Glade.Widget] private RadioButton  tiny_size, small_size, medium_size, 
                                          large_size, x_large_size, original_size;
            [Glade.Widget] private CheckButton  rotate_check;

            int photo_index;
            bool clean;
            static uint timer = 0;
            long Orig_Photo_Size    = 0;
            double scale_percentage = 0.3;
            bool keep_exif          = true;
            
            // The different sizes we can shrink to foto to. See RadioButton above for labels.
            static int[] sizes            = { 0, 320,       480,  640,  800,  1024 };
            
            // Estimated size relative to original after shrinking down the photo. 
            double[] avg_scale_ref  = { 0, 0.0186,    0.0348,     0.0532,     0.0826,     0.1234 };
            
            static int NoOfSizes    = sizes.Length;
            double[] avg_scale      = new double [NoOfSizes];
            System.Collections.ArrayList tmp_paths; // temporary resized image file name
            string tmp_mail_dir;    // To temporary keep the resized images

            ThreadProgressDialog progress_dialog;
            System.Threading.Thread command_thread;
            IBrowsableCollection selection;

            public SendEmail (IBrowsableCollection selection) : base ("mail_dialog")
            {
                  this.selection = selection;
                  
                  // Set default values in dialog. Fetch from Preferences.
                  switch ((int) Preferences.Get (Preferences.EXPORT_EMAIL_SIZE)) {
                        case 0 :  original_size.Active = true; break;
                        case 1 :  tiny_size.Active = true; break;
                        case 2 :  small_size.Active = true; break;
                        case 3 :  medium_size.Active = true; break;
                        case 4 :  large_size.Active = true; break;
                        case 5 :  x_large_size.Active = true; break;
                        default: break;
                  }
                  rotate_check.Active = (bool) Preferences.Get (Preferences.EXPORT_EMAIL_ROTATE);
                  
                  IconView view = new IconView (selection);
                  view.DisplayDates = false;
                  view.DisplayTags = false;

                  Dialog.Modal = false;
                  Dialog.TransientFor = null;

                  string path;
                  System.IO.FileInfo file_info;

                  // Calculate total original filesize 
                  foreach (Photo photo in selection.Items) {
                        if (photo != null) {
                              path = photo.GetVersionPath(photo.DefaultVersionId);
                              if (System.IO.File.Exists (path)) {
                                    file_info = new System.IO.FileInfo (path);
                                    Orig_Photo_Size += file_info.Length;
                              } // if file exists
                        } // if photo != null
                  } // foreach

                  for (int k = 0; k < avg_scale_ref.Length; k++)
                        avg_scale[k] = avg_scale_ref[k];


                  // Calculate approximate size shrinking, use first photo, and shrink to medium size as base.
                  Photo scalephoto = selection.Items [0] as Photo;                  
                  if (scalephoto != null) {
                        
                        // Get first photos file size
                        file_info = new System.IO.FileInfo (scalephoto.GetVersionPath(scalephoto.DefaultVersionId));
                        long orig_size = file_info.Length;
                        
                        // Get filesize of first photo after resizing it to medium size
                        path = PixbufUtils.Resize (scalephoto.GetVersionPath(scalephoto.DefaultVersionId), sizes[3], true);
                        file_info = new System.IO.FileInfo (path);
                        long new_size = file_info.Length;
                        
                        // Delete the just created temporary resized photo
                        System.IO.File.Delete (path);
                        
                        if (orig_size > 0) {
                        
                              // Get the factor (scale) between original and resized medium size.
                              scale_percentage = 1 - ( (float) (orig_size - new_size) / orig_size);
                              
                              // What is the relation between the estimated medium scale factor, and reality?
                              double scale_scale = scale_percentage / avg_scale_ref[3];
                              
                              //System.Console.WriteLine ("scale_percentage {0}, ref {1}, relative {2}", 
                              //    scale_percentage, avg_scale_ref[3], scale_scale  );

                              // Re-Calculate the proper relation per size
                              for (int k = 0; k < avg_scale_ref.Length; k++) {
                                    avg_scale[k] = avg_scale_ref[k] * scale_scale;
                              //    System.Console.WriteLine ("avg_scale[{0}]={1} (was {2})", 
                              //          k, avg_scale[k], avg_scale_ref[k]  );
                              }
                        }

                  }

                  NumberOfPictures.Text   = selection.Count.ToString();
                  TotalOriginalSize.Text  = ToHumanReadableSize (Orig_Photo_Size);
                  
                  UpdateEstimatedSize();

                  //thumb_scrolledwindow.Add (view);
                  Dialog.ShowAll ();

                  //LoadHistory ();

                  Dialog.Response += HandleResponse;
            }

            private static string ToHumanReadableSize (long in_size)
            {
                  string tmp_str = "";
                  float tmp_size = in_size;
                  int k = 0;
                  string[] size_abr = {"bytes", "kB", "MB", "GB", "TB" };

                  while (tmp_size > 700) { //it's easier to read 0.9MB than 932kB
                        tmp_size = tmp_size / 1024;
                        k++;
                  }

                  if (tmp_size < 7)
                        tmp_str = tmp_size.ToString ("0.##");
                  else if (tmp_size < 70)
                        tmp_str = tmp_size.ToString ("##.#");
                  else
                        tmp_str = tmp_size.ToString ("#,###");

                  if (k < size_abr.Length)
                        return tmp_str + " " + size_abr[k];
                  else
                        return in_size.ToString();
                }
            
            private int GetScaleSize()
            {
                  // not only convert dialog size to pixel size, but also set preferences se we use same size next time
                  int size_number = 0; // default to original size
                  if (tiny_size.Active) 
                        size_number = 1;
                  if (small_size.Active) 
                        size_number = 2;
                  if (medium_size.Active) 
                        size_number = 3;
                  if (large_size.Active) 
                        size_number = 4;
                  if (x_large_size.Active) 
                        size_number = 5;
                  
                  Preferences.Set (Preferences.EXPORT_EMAIL_SIZE, size_number);                 
                  return sizes [ size_number ];       
            }
            
            private int GetScaleIndex ()
            {
                  int scale = GetScaleSize();
                  for (int k = 0; k < sizes.Length; k++)
                        if (sizes[k] == scale)
                              return k;
                  return 0;
            }

            private void UpdateEstimatedSize()
            {
                        int new_size_index;
                        long new_approx_total_size;
                        string approxresult;
                        
                        new_size_index = GetScaleIndex();
                        if (new_size_index == 0)
                              new_approx_total_size = Orig_Photo_Size;
                        else
                              new_approx_total_size = System.Convert.ToInt64(Orig_Photo_Size * avg_scale [new_size_index]);

                        approxresult = ToHumanReadableSize (new_approx_total_size);
                        ApproxNewSize.Text      = approxresult;   

            }

            public void on_size_toggled (object o, EventArgs args) 
            {
                  UpdateEstimatedSize();
                  
                  // Only enable the rotate option if Original size is selected.
                  rotate_check.Sensitive = original_size.Active;
            }


            private bool DeleteTempFile ()
            {
//                System.Console.WriteLine ("Lets delete all temp files");

                  // Lets delete all the temporary files now
                  for (int k = 0; k < tmp_paths.Count; k++) {
                        if (System.IO.File.Exists((string) tmp_paths[k])) {
                              System.IO.File.Delete ((string) tmp_paths[k]);
//                            System.Console.WriteLine ("Lets delete temp file {0}", tmp_paths[k]);
                        }
                  }
                  
                  if (System.IO.Directory.Exists(tmp_mail_dir)) {
                        System.IO.Directory.Delete(tmp_mail_dir);
//                      System.Console.WriteLine ("Lets delete temp dir {0}", tmp_mail_dir);
                  }
                  
                  return false;
            }

            private void HandleResponse (object sender, Gtk.ResponseArgs args)
            {
                  string tmp_path;

                  long new_size = 0;
//                long orig_size = 0;
                  long actual_total_size = 0;
                  int size = 0;
                  System.IO.FileInfo file_info;
                  bool UserCancelled = false;
                  bool rotate = true;

                  // Lets remove the mail "create mail" dialog
                  Dialog.Destroy();             

                  if (args.ResponseId != Gtk.ResponseType.Ok) {
                        return;
                  }
                  ProgressDialog progress_dialog = null;
                  actual_total_size = 0;
            
                  progress_dialog = new ProgressDialog (
                                    Mono.Posix.Catalog.GetString ("Preparing email"),
                                    ProgressDialog.CancelButtonType.Stop,
                                    selection.Items.Length, 
                                    parent_window);
                  
                  size = GetScaleSize(); // Which size should we scale to. 0 --> Original
                  
                  rotate = rotate_check.Active;  // Should we automatically rotate original photos.
                  Preferences.Set (Preferences.EXPORT_EMAIL_ROTATE, rotate);

                  // Initiate storage for temporary files to be deleted later
                  tmp_paths = new System.Collections.ArrayList();
                  
                  // Create a tmp directory.
                  tmp_mail_dir = System.IO.Path.GetTempFileName ();     // Create a tmp file    
                  System.IO.File.Delete (tmp_mail_dir);                 // Delete above tmp file
                  System.IO.Directory.CreateDirectory (tmp_mail_dir);   // Create a directory with above tmp name
                  
                  System.Text.StringBuilder url = new System.Text.StringBuilder ("mailto:?subject=my%20photos");

                  foreach (Photo photo in selection.Items) {
                  
                        if ( (photo != null) && (!UserCancelled) ) {

                              if (progress_dialog != null)
                                    UserCancelled = progress_dialog.Update (String.Format 
                                          (Mono.Posix.Catalog.GetString ("Exporting picture \"{0}\""), photo.Name));
                                          
                              if (UserCancelled)
                                    break;
                                    
                              file_info = new System.IO.FileInfo (photo.GetVersionPath(photo.DefaultVersionId));
//                            orig_size = file_info.Length;

                              // Prepare a tmp_mail file name
                              tmp_path =  FileImportBackend.UniqueName (
                                    tmp_mail_dir,
                                    System.IO.Path.GetFileName(photo.GetVersionPath(photo.DefaultVersionId))
                                    );

                              if (size == 0) {
                                    // User wants to send original photos, no resizing required.
                                    if (rotate) {
                                          Exif.ExifData exif_data = new Exif.ExifData (photo.GetVersionPath(photo.DefaultVersionId));
                                          PixbufOrientation orientation = PixbufUtils.GetOrientation (exif_data);
                                          if (orientation == PixbufOrientation.RightTop) {
                                                JpegUtils.Transform (photo.GetVersionPath(photo.DefaultVersionId), tmp_path, JpegUtils.TransformType.Rotate90);
                                                tmp_paths.Add (tmp_path);
                                          } else if (orientation == PixbufOrientation.LeftBottom) {
                                                JpegUtils.Transform (photo.GetVersionPath(photo.DefaultVersionId), tmp_path, JpegUtils.TransformType.Rotate270);
                                                tmp_paths.Add (tmp_path);
                                          } else
                                                tmp_path = photo.GetVersionPath(photo.DefaultVersionId);
                                    } else {
                                          // No need to rotate
                                          tmp_path = photo.GetVersionPath(photo.DefaultVersionId);
                                    }
                              } else {
                                    // resize (including rotate) original photo, and put result in tmp_photo file
                                    PixbufUtils.Resize (
                                          photo.GetVersionPath(photo.DefaultVersionId),
                                          tmp_path, 
                                          size, 
                                          keep_exif);

                                    // tmp_path = PixbufUtils.Resize (photo.GetVersionPath(photo.DefaultVersionId), size, keep_exif);
                                    tmp_paths.Add (tmp_path); // Keep the new tmp_path, so we can delete it later
                              }

                              System.Console.WriteLine ("Scaling photo {0}", tmp_path);                     

                              url.Append ("&attach=" + tmp_path);
                              
                              // Update the running total of the actual file sizes.
                              file_info = new System.IO.FileInfo (tmp_path);
                              new_size = file_info.Length;
                              actual_total_size += new_size;

                              // Update dialog to indicate Actual size!
                              // This is currently disabled, since the dialog box is not visible at this stage.
                              // string approxresult = ToHumanReadableSize (actual_total_size);
                              // ActualMailSize.Text = approxresult;    


                              //System.Console.WriteLine ("Orig file size {0}, New file size {1}, % {4}, Scaled to size {2}, new name {3}", 
                              //orig_size, new_size, size, tmp_path, 1 - ((orig_size-new_size)/orig_size));
                        }
                  } // foreach
                  
                  if (progress_dialog != null) 
                        progress_dialog.Destroy (); // No need to keep this window

                  if (UserCancelled)
                        DeleteTempFile();
                  else {            
                        // Send the mail :)
                        //System.Console.WriteLine ("Mail command {0}", url.ToString()); 
                        GnomeUtil.UrlShow (parent_window, url.ToString ());

                        // Check if we have any temporary files to be deleted
                        if (tmp_paths.Count > 0) {
                              // Fetch timeout value from preferences. In seconds. Needs to be multiplied with 1000 to get msec
                              uint delete_timeout;
                              delete_timeout = (uint) ( (int) Preferences.Get (Preferences.EXPORT_EMAIL_DELETE_TIMEOUT_SEC) );
                              delete_timeout = delete_timeout * 1000; // to get milliseconds.

                              // Start a timer and when it occurs, delete the temp files.
                              timer = GLib.Timeout.Add (delete_timeout, new GLib.TimeoutHandler (DeleteTempFile));
                        }
                  }
            }
      }
}

Generated by  Doxygen 1.6.0   Back to index