/* * Copyright (C) 2005 Alessandro Gervaso * * 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 Place - Suite 330, * Boston, MA 02111-1307, USA. */ //This should be used to export the selected pics to an original gallery //located on a VFS location. using System; using System.IO; using System.Runtime.InteropServices; using Mono.Unix; using ICSharpCode.SharpZipLib.Checksums; using ICSharpCode.SharpZipLib.Zip; using ICSharpCode.SharpZipLib.GZip; namespace FSpot { public class FolderExport : GladeDialog, FSpot.Extensions.IExporter { IBrowsableCollection selection; [Glade.Widget] Gtk.ScrolledWindow thumb_scrolledwindow; [Glade.Widget] Gtk.Entry name_entry; [Glade.Widget] Gtk.Entry description_entry; //[Glade.Widget] Gtk.CheckButton meta_check; [Glade.Widget] Gtk.CheckButton scale_check; [Glade.Widget] Gtk.CheckButton rotate_check; [Glade.Widget] Gtk.CheckButton open_check; [Glade.Widget] Gtk.RadioButton static_radio; [Glade.Widget] Gtk.RadioButton original_radio; [Glade.Widget] Gtk.RadioButton plain_radio; [Glade.Widget] Gtk.SpinButton size_spin; [Glade.Widget] Gtk.HBox chooser_hbox; Gnome.Vfs.Uri dest; Gtk.FileChooserButton uri_chooser; int photo_index; bool open; bool scale; bool rotate; int size; string description; string gallery_name = "Gallery"; // FIME this needs to be a real temp directory string gallery_path = Path.Combine (Path.GetTempPath (), "f-spot-original-" + System.DateTime.Now.Ticks.ToString ()); FSpot.ThreadProgressDialog progress_dialog; System.Threading.Thread command_thread; public FolderExport () : base ("folder_export_dialog") {} public void Run (IBrowsableCollection selection) { /* Gnome.Vfs.ModuleCallbackFullAuthentication auth = new Gnome.Vfs.ModuleCallbackFullAuthentication (); auth.Callback += new Gnome.Vfs.ModuleCallbackHandler (HandleAuth); auth.SetDefault (); auth.Push (); Gnome.Vfs.ModuleCallbackAuthentication mauth = new Gnome.Vfs.ModuleCallbackAuthentication (); mauth.Callback += new Gnome.Vfs.ModuleCallbackHandler (HandleAuth); mauth.SetDefault (); mauth.Push (); Gnome.Vfs.ModuleCallbackSaveAuthentication sauth = new Gnome.Vfs.ModuleCallbackSaveAuthentication (); sauth.Callback += new Gnome.Vfs.ModuleCallbackHandler (HandleAuth); sauth.SetDefault (); sauth.Push (); Gnome.Vfs.ModuleCallbackStatusMessage msg = new Gnome.Vfs.ModuleCallbackStatusMessage (); msg.Callback += new Gnome.Vfs.ModuleCallbackHandler (HandleMsg); msg.SetDefault (); msg.Push (); */ this.selection = selection; IconView view = (IconView) new IconView (selection); view.DisplayDates = false; view.DisplayTags = false; Dialog.Modal = false; Dialog.TransientFor = null; thumb_scrolledwindow.Add (view); HandleSizeActive (null, null); name_entry.Text = gallery_name; string uri_path = System.IO.Path.Combine (FSpot.Global.HomeDirectory, "Desktop"); if (!System.IO.Directory.Exists (uri_path)) uri_path = FSpot.Global.HomeDirectory; uri_chooser = new Gtk.FileChooserButton (Catalog.GetString ("Select Export Folder"), Gtk.FileChooserAction.SelectFolder); uri_chooser.LocalOnly = false; if (Preferences.Get (Preferences.EXPORT_FOLDER_URI) != null && Preferences.Get (Preferences.EXPORT_FOLDER_URI) as string != String.Empty) uri_chooser.SetUri (Preferences.Get (Preferences.EXPORT_FOLDER_URI) as string); else uri_chooser.SetFilename (uri_path); chooser_hbox.PackStart (uri_chooser); Dialog.ShowAll (); //LoadHistory (); Dialog.Response += HandleResponse; LoadPreference (Preferences.EXPORT_FOLDER_SCALE); LoadPreference (Preferences.EXPORT_FOLDER_SIZE); LoadPreference (Preferences.EXPORT_FOLDER_OPEN); LoadPreference (Preferences.EXPORT_FOLDER_ROTATE); LoadPreference (Preferences.EXPORT_FOLDER_METHOD); } public void HandleSizeActive (object sender, System.EventArgs args) { size_spin.Sensitive = scale_check.Active; } public void Upload () { // FIXME use mkstemp Gnome.Vfs.Result result = Gnome.Vfs.Result.Ok; try { Dialog.Hide (); Gnome.Vfs.Uri source = new Gnome.Vfs.Uri (Path.Combine (gallery_path, gallery_name)); Gnome.Vfs.Uri target = dest.Clone(); target = target.AppendFileName(source.ExtractShortName ()); if (dest.IsLocal) gallery_path = Gnome.Vfs.Uri.GetLocalPathFromUri (dest.ToString ()); progress_dialog.Message = Catalog.GetString ("Building Gallery"); progress_dialog.Fraction = 0.0; FolderGallery gallery; if (static_radio.Active) { gallery = new HtmlGallery (selection, gallery_path, gallery_name); } else if (original_radio.Active) { gallery = new OriginalGallery (selection, gallery_path, gallery_name); } else { gallery = new FolderGallery (selection, gallery_path, gallery_name); } if (scale) { System.Console.WriteLine ("setting scale to {0}", size); gallery.SetScale (size); } else { System.Console.WriteLine ("Exporting full size image"); } if (rotate) { System.Console.WriteLine ("Exporting rotated image"); gallery.SetRotate(); } gallery.Description = description; gallery.GenerateLayout (); Filters.FilterSet filter_set = new Filters.FilterSet (); if (scale) filter_set.Add (new Filters.ResizeFilter ((uint) size)); else if (rotate) filter_set.Add (new Filters.OrientationFilter ()); filter_set.Add (new Filters.ChmodFilter ()); filter_set.Add (new Filters.UniqueNameFilter (gallery_path)); for (int photo_index = 0; photo_index < selection.Count; photo_index++) { try { progress_dialog.Message = System.String.Format (Catalog.GetString ("Uploading picture \"{0}\""), selection[photo_index].Name); progress_dialog.Fraction = photo_index / (double) selection.Count; gallery.ProcessImage (photo_index, filter_set); progress_dialog.ProgressText = System.String.Format (Catalog.GetString ("{0} of {1}"), photo_index, selection.Count); } catch (Exception e) { progress_dialog.Message = String.Format (Catalog.GetString ("Error uploading picture \"{0}\" to Gallery:{2}{1}"), selection[photo_index].Name, e.Message, Environment.NewLine); progress_dialog.ProgressText = Catalog.GetString ("Error"); if (progress_dialog.PerformRetrySkip ()) photo_index--; } } //create the zip tarballs for original if (gallery is OriginalGallery && (bool)Preferences.Get(Preferences.EXPORT_FOLDER_INCLUDE_TARBALLS)) (gallery as OriginalGallery).CreateZip (); // we've created the structure, now if the destination was local we are done // otherwise we xfer if (!dest.IsLocal) { Console.WriteLine(target); System.Console.WriteLine ("Xfering {0} to {1}", source.ToString (), target.ToString ()); result = Gnome.Vfs.Xfer.XferUri (source, target, Gnome.Vfs.XferOptions.Default, Gnome.Vfs.XferErrorMode.Abort, Gnome.Vfs.XferOverwriteMode.Replace, Progress); } if (result == Gnome.Vfs.Result.Ok) { progress_dialog.Message = Catalog.GetString ("Done Sending Photos"); progress_dialog.Fraction = 1.0; progress_dialog.ProgressText = Catalog.GetString ("Transfer Complete"); progress_dialog.ButtonLabel = Gtk.Stock.Ok; } else { progress_dialog.ProgressText = result.ToString (); progress_dialog.Message = Catalog.GetString ("Error While Transferring"); } if (open) { GnomeUtil.UrlShow (null, target.ToString ()); } // Save these settings for next time Preferences.Set (Preferences.EXPORT_FOLDER_SCALE, scale); Preferences.Set (Preferences.EXPORT_FOLDER_SIZE, size); Preferences.Set (Preferences.EXPORT_FOLDER_OPEN, open); Preferences.Set (Preferences.EXPORT_FOLDER_ROTATE, rotate); Preferences.Set (Preferences.EXPORT_FOLDER_METHOD, static_radio.Active ? "static" : original_radio.Active ? "original" : "folder" ); Preferences.Set (Preferences.EXPORT_FOLDER_URI, uri_chooser.Uri); } catch (System.Exception e) { // Console.WriteLine (e); progress_dialog.Message = e.ToString (); progress_dialog.ProgressText = Catalog.GetString ("Error Transferring"); } finally { // if the destination isn't local then we want to remove the temp directory we // created. if (!dest.IsLocal) System.IO.Directory.Delete (gallery_path, true); Gtk.Application.Invoke (delegate { Dialog.Destroy(); }); } } private int Progress (Gnome.Vfs.XferProgressInfo info) { progress_dialog.ProgressText = info.Phase.ToString (); if (info.BytesTotal > 0) { progress_dialog.Fraction = info.BytesCopied / (double)info.BytesTotal; } switch (info.Status) { case Gnome.Vfs.XferProgressStatus.Vfserror: progress_dialog.Message = Catalog.GetString ("Error: Error while transferring; Aborting"); return (int)Gnome.Vfs.XferErrorAction.Abort; case Gnome.Vfs.XferProgressStatus.Overwrite: progress_dialog.ProgressText = Catalog.GetString ("Error: File Already Exists; Aborting"); return (int)Gnome.Vfs.XferOverwriteAction.Abort; default: return 1; } } private void HandleMsg (Gnome.Vfs.ModuleCallback cb) { Gnome.Vfs.ModuleCallbackStatusMessage msg = cb as Gnome.Vfs.ModuleCallbackStatusMessage; System.Console.WriteLine ("{0}", msg.Message); } private void HandleAuth (Gnome.Vfs.ModuleCallback cb) { Gnome.Vfs.ModuleCallbackFullAuthentication fcb = cb as Gnome.Vfs.ModuleCallbackFullAuthentication; System.Console.Write ("Enter your username ({0}): ", fcb.Username); string username = System.Console.ReadLine (); System.Console.Write ("Enter your password : "); string passwd = System.Console.ReadLine (); if (username.Length > 0) fcb.Username = username; fcb.Password = passwd; } private void HandleResponse (object sender, Gtk.ResponseArgs args) { if (args.ResponseId != Gtk.ResponseType.Ok) { // FIXME this is to work around a bug in gtk+ where // the filesystem events are still listened to when // a FileChooserButton is destroyed but not finalized // and an event comes in that wants to update the child widgets. Dialog.Destroy (); uri_chooser.Dispose (); uri_chooser = null; return; } dest = new Gnome.Vfs.Uri (uri_chooser.Uri); open = open_check.Active; scale = scale_check.Active; rotate = rotate_check.Active; gallery_name = name_entry.Text; if (description_entry != null) description = description_entry.Text; if (scale) size = size_spin.ValueAsInt; command_thread = new System.Threading.Thread (new System.Threading.ThreadStart (Upload)); command_thread.Name = Catalog.GetString ("Transferring Pictures"); //FIXME: get the files/dirs count in a cleaner way than (* 5 + 2(zip) + 9) // selection * 5 (original, mq, lq, thumbs, comments) // 2: zipfiles // 9: directories + info.txt + .htaccess // this should actually be 1 anyway, because we transfer just one dir progress_dialog = new FSpot.ThreadProgressDialog (command_thread, 1); progress_dialog.Start (); } void LoadPreference (string key) { object val = Preferences.Get (key); if (val == null) return; //System.Console.WriteLine ("Setting {0} to {1}", key, val); switch (key) { case Preferences.EXPORT_FOLDER_SCALE: if (scale_check.Active != (bool) val) scale_check.Active = (bool) val; break; case Preferences.EXPORT_FOLDER_SIZE: size_spin.Value = (double) (int) val; break; case Preferences.EXPORT_FOLDER_OPEN: if (open_check.Active != (bool) val) open_check.Active = (bool) val; break; case Preferences.EXPORT_FOLDER_ROTATE: if (rotate_check.Active != (bool) val) rotate_check.Active = (bool) val; break; case Preferences.EXPORT_FOLDER_METHOD: static_radio.Active = (string) val == "static"; original_radio.Active = (string) val == "original"; plain_radio.Active = (string) val == "folder"; break; } } } internal class FolderGallery { protected IBrowsableCollection collection; protected string gallery_name; protected string gallery_path; protected bool scale; protected int size; protected bool rotate; protected string description; protected string language; protected System.Uri destination; protected ScaleRequest [] requests; protected string [] pixbuf_keys = { "quality", null }; protected string [] pixbuf_values = { "95", null }; protected struct ScaleRequest { public string Name; public int Width; public int Height; public bool Skip; public bool CopyExif; public ScaleRequest (string name, int width, int height, bool skip) : this (name, width, height, skip, false) {} public ScaleRequest (string name, int width, int height, bool skip, bool exif) { this.Name = name != null ? name : String.Empty; this.Width = width; this.Height = height; this.Skip = skip; this.CopyExif = exif; } public static ScaleRequest Default = new ScaleRequest (String.Empty, 0, 0, false); public bool AvoidScale (int size) { return (size < this.Width && size < this.Height && this.Skip); } } internal FolderGallery (IBrowsableCollection selection, string path, string gallery_name) { this.collection = selection; this.gallery_name = gallery_name; this.gallery_path = Path.Combine (path, gallery_name); this.requests = new ScaleRequest [] { ScaleRequest.Default }; } public virtual void GenerateLayout () { MakeDir (gallery_path); } protected virtual string ImageName (int image_num) { return System.IO.Path.GetFileName(FileImportBackend.UniqueName(gallery_path, System.IO.Path.GetFileName (collection [image_num].DefaultVersionUri.LocalPath))); } public void ProcessImage (int image_num, Filters.FilterSet filter_set) { IBrowsableItem photo = collection [image_num]; string photo_path = photo.DefaultVersionUri.LocalPath; string path; ScaleRequest req; req = requests [0]; MakeDir (SubdirPath (req.Name)); path = SubdirPath (req.Name, ImageName (image_num)); using (Filters.FilterRequest request = new Filters.FilterRequest (photo.DefaultVersionUri)) { filter_set.Convert (request); if (request.Current.LocalPath == path) request.Preserve(request.Current); else File.Copy (request.Current.LocalPath, path, true); if (photo != null && photo is Photo && Core.Database != null) { Core.Database.Exports.Create ((photo as Photo).Id, (photo as Photo).DefaultVersionId, ExportStore.FolderExportType, // FIXME this is wrong, the final path is the one // after the Xfer. UriList.PathToFileUriEscaped (path).ToString ()); } using (Exif.ExifData data = new Exif.ExifData (photo_path)) { for (int i = 1; i < requests.Length; i++) { req = requests [i]; if (scale && req.AvoidScale (size)) continue; Filters.FilterSet req_set = new Filters.FilterSet (); req_set.Add (new Filters.ResizeFilter ((uint)Math.Max (req.Width, req.Height))); if ((bool)Preferences.Get (Preferences.EXPORT_FOLDER_SHARPEN)) { if (req.Name == "lq") req_set.Add (new Filters.SharpFilter (0.1, 2, 4)); if (req.Name == "thumbs") req_set.Add (new Filters.SharpFilter (0.1, 2, 5)); } using (Filters.FilterRequest tmp_req = new Filters.FilterRequest (photo.DefaultVersionUri)) { req_set.Convert (tmp_req); MakeDir (SubdirPath (req.Name)); path = SubdirPath (req.Name, ImageName (image_num)); System.IO.File.Copy (tmp_req.Current.LocalPath, path, true); } } } } } protected string MakeDir (string path) { try { Directory.CreateDirectory (path); } catch { Console.WriteLine ("Error in creating directory " + path); } return path; } protected string SubdirPath (string subdir) { return SubdirPath (subdir, null); } protected string SubdirPath (string subdir, string file) { string path = Path.Combine (gallery_path, subdir); if (file != null) path = Path.Combine (path, file); return path; } public string GalleryPath { get { return gallery_path; } } public string Description { get { return description; } set { description = value; } } public string Language { get { if (language == null) language=GetLanguage(); return language; } } public Uri Destination { get { return destination; } set { this.destination = value; } } public void SetScale (int size) { this.scale = true; this.size = size; requests [0].Width = size; requests [0].Height = size; } public void SetRotate () { this.rotate = true; } private string GetLanguage() { string language; if ((language = Environment.GetEnvironmentVariable ("LC_ALL")) == null) if ((language = Environment.GetEnvironmentVariable ("LC_MESSAGES")) == null) if ((language = Environment.GetEnvironmentVariable ("LANG")) == null) language = "en"; if (language.IndexOf('.') >= 0) language = language.Substring(0,language.IndexOf('.')); if (language.IndexOf('@') >= 0) language = language.Substring(0,language.IndexOf('@')); language = language.Replace('_','-'); return language; } } class OriginalGallery : FolderGallery { public OriginalGallery (IBrowsableCollection selection, string path, string name) : base (selection, path, name) { requests = new ScaleRequest [] { new ScaleRequest ("hq", 0, 0, false), new ScaleRequest ("mq", 800, 600, true), new ScaleRequest ("lq", 640, 480, false, true), new ScaleRequest ("thumbs", 120, 120, false) }; } public override void GenerateLayout () { base.GenerateLayout (); MakeDir (SubdirPath ("comments")); CreateHtaccess(); CreateInfo(); SetTime (); } protected override string ImageName (int photo_index) { return String.Format ("img-{0}.jpg", photo_index + 1); } private string AlternateName (int photo_index, string extension) { return System.IO.Path.GetFileNameWithoutExtension (ImageName (photo_index)) + extension; } private void SetTime () { try { for (int i = 0; i < collection.Count; i++) CreateComments (collection [i].DefaultVersionUri.LocalPath, i); Directory.SetLastWriteTimeUtc(gallery_path, collection [0].Time); } catch (System.Exception e) { System.Console.WriteLine (e.ToString ()); } } internal void CreateZip () { MakeDir (SubdirPath ("zip")); try { if (System.IO.Directory.Exists (SubdirPath ("mq"))) CreateZipFile("mq"); if (System.IO.Directory.Exists (SubdirPath ("hq"))) CreateZipFile("hq"); } catch (System.Exception e) { System.Console.WriteLine (e.ToString ()); } } private void CreateComments(string photo_path, int photo_index) { StreamWriter comment = File.CreateText(SubdirPath ("comments", photo_index + 1 + ".txt")); comment.Write("photo " + (photo_index + 1) + " "); comment.Write (collection [photo_index].Description + Environment.NewLine); comment.Close(); } private void CreateZipFile(string img_quality) { string[] filenames = Directory.GetFiles(SubdirPath (img_quality)); Crc32 crc = new Crc32(); ZipOutputStream s = new ZipOutputStream(File.Create(SubdirPath ("zip", img_quality + ".zip"))); s.SetLevel(0); foreach (string file in filenames) { FileStream fs = File.OpenRead(file); byte[] buffer = new byte[fs.Length]; fs.Read(buffer, 0, buffer.Length); ZipEntry entry = new ZipEntry(Path.GetFileName(file)); entry.DateTime = DateTime.Now; // set Size and the crc, because the information // about the size and crc should be stored in the header // if it is not set it is automatically written in the footer. // (in this case size == crc == -1 in the header) // Some ZIP programs have problems with zip files that don't store // the size and crc in the header. entry.Size = fs.Length; fs.Close(); crc.Reset(); crc.Update(buffer); entry.Crc = crc.Value; s.PutNextEntry(entry); s.Write(buffer, 0, buffer.Length); } s.Finish(); s.Close(); } private void CreateHtaccess() { StreamWriter htaccess = File.CreateText(Path.Combine (gallery_path,".htaccess")); htaccess.Write("" + Environment.NewLine + "\tdeny from all" + Environment.NewLine+ "" + Environment.NewLine); htaccess.Close(); } private void CreateInfo() { StreamWriter info = File.CreateText(Path.Combine (gallery_path, "info.txt")); info.WriteLine("name|" + gallery_name); info.WriteLine("date|" + collection [0].Time.Date.ToString ("dd.MM.yyyy")); info.WriteLine("description|" + description); info.Close(); } } class HtmlGallery : FolderGallery { int current; int perpage = 16; string stylesheet = "f-spot-simple.css"; string altstylesheet = "f-spot-simple-white.css"; string javascript = "f-spot.js"; static string light = Catalog.GetString("Light"); static string dark = Catalog.GetString("Dark"); public HtmlGallery (IBrowsableCollection selection, string path, string name) : base (selection, path, name) { requests = new ScaleRequest [] { new ScaleRequest ("hq", 0, 0, false), new ScaleRequest ("mq", 480, 320, false), new ScaleRequest ("thumbs", 120, 90, false) }; } protected override string ImageName (int photo_index) { return String.Format ("img-{0}.jpg", photo_index + 1); } public override void GenerateLayout () { if (collection.Count == 0) return; base.GenerateLayout (); IBrowsableItem [] photos = collection.Items; int i; for (i = 0; i < photos.Length; i++) SavePhotoHtmlIndex (i); for (i = 0; i < PageCount; i++) SaveHtmlIndex (i); MakeDir (SubdirPath ("style")); System.Reflection.Assembly assembly = System.Reflection.Assembly.GetCallingAssembly (); using (Stream s = assembly.GetManifestResourceStream (stylesheet)) { using (Stream fs = System.IO.File.Open (SubdirPath ("style", stylesheet), System.IO.FileMode.Create)) { byte [] buffer = new byte [8192]; int n; while ((n = s.Read (buffer, 0, buffer.Length)) != 0) fs.Write (buffer, 0, n); } } /* quick and stupid solution this should have been iterated over an array of stylesheets, really */ using (Stream s = assembly.GetManifestResourceStream (altstylesheet)) { using (Stream fs = System.IO.File.Open (SubdirPath ("style", altstylesheet), System.IO.FileMode.Create)) { byte [] buffer = new byte [8192]; int n = 0; while ((n = s.Read (buffer, 0, buffer.Length)) != 0) fs.Write (buffer, 0, n); } } /* Javascript for persistant style change */ MakeDir (SubdirPath ("script")); using (Stream s = assembly.GetManifestResourceStream (javascript)) { using (Stream fs = System.IO.File.Open (SubdirPath ("script", javascript), System.IO.FileMode.Create)) { byte [] buffer = new byte [8192]; int n = 0; while ((n = s.Read (buffer, 0, buffer.Length)) != 0) fs.Write (buffer, 0, n); } } } public int PageCount { get { return (int) System.Math.Ceiling (collection.Items.Length / (double)perpage); } } public string PhotoThumbPath (int item) { return System.IO.Path.Combine (requests [2].Name, ImageName (item)); } public string PhotoWebPath (int item) { return System.IO.Path.Combine (requests [1].Name, ImageName (item)); } public string PhotoOriginalPath (int item) { return System.IO.Path.Combine (requests [0].Name, ImageName (item)); } public string PhotoIndexPath (int item) { return (System.IO.Path.GetFileNameWithoutExtension (ImageName (item)) + ".html"); } public static void WritePageNav (System.Web.UI.HtmlTextWriter writer, string id, string url, string name) { writer.AddAttribute ("id", id); writer.RenderBeginTag ("div"); writer.AddAttribute ("href", url); writer.RenderBeginTag ("a"); writer.Write (name); writer.RenderEndTag (); writer.RenderEndTag (); } public void SavePhotoHtmlIndex (int i) { System.IO.StreamWriter stream = System.IO.File.CreateText (SubdirPath (PhotoIndexPath (i))); System.Web.UI.HtmlTextWriter writer = new System.Web.UI.HtmlTextWriter (stream); //writer.Indent = 4; //writer.Write (""); writer.WriteLine (""); writer.AddAttribute ("xmlns", "http://www.w3.org/1999/xhtml"); writer.AddAttribute ("xml:lang", this.Language); writer.RenderBeginTag ("html"); WriteHeader (writer); writer.AddAttribute ("onload", "checkForTheme()"); writer.RenderBeginTag ("body"); writer.AddAttribute ("class", "container1"); writer.RenderBeginTag ("div"); writer.AddAttribute ("class", "header"); writer.RenderBeginTag ("div"); writer.AddAttribute ("id", "title"); writer.RenderBeginTag ("div"); writer.Write (gallery_name); writer.RenderEndTag (); writer.AddAttribute ("class", "navi"); writer.RenderBeginTag ("div"); if (i > 0) // Abbreviation of previous WritePageNav (writer, "prev", PhotoIndexPath (i - 1), Catalog.GetString("Prev")); WritePageNav (writer, "index", IndexPath (i / perpage), Catalog.GetString("Index")); if (i < collection.Count -1) WritePageNav (writer, "next", PhotoIndexPath (i + 1), Catalog.GetString("Next")); writer.RenderEndTag (); //navi writer.RenderEndTag (); //header writer.AddAttribute ("class", "photo"); writer.RenderBeginTag ("div"); writer.AddAttribute ("href", PhotoOriginalPath (i)); writer.RenderBeginTag ("a"); writer.AddAttribute ("src", PhotoWebPath (i)); writer.AddAttribute ("alt", "#"); writer.RenderBeginTag ("img"); writer.RenderEndTag (); writer.RenderEndTag (); // a writer.AddAttribute ("id", "description"); writer.RenderBeginTag ("div"); writer.Write (collection [i].Description); writer.RenderEndTag (); writer.RenderEndTag (); //Style Selection Box writer.AddAttribute ("id", "styleboxcontainer"); writer.RenderBeginTag ("div"); writer.AddAttribute ("id", "stylebox"); writer.AddAttribute ("style", "display: none;"); writer.RenderBeginTag ("div"); writer.RenderBeginTag("ul"); writer.RenderBeginTag("li"); writer.AddAttribute ("href", "#"); writer.AddAttribute ("title", dark); writer.AddAttribute ("onclick", "setActiveStyleSheet('" + dark + "')"); writer.RenderBeginTag("a"); writer.Write (dark); writer.RenderEndTag (); //a writer.RenderEndTag (); //li writer.RenderBeginTag("li"); writer.AddAttribute ("href", "#"); writer.AddAttribute ("title", light); writer.AddAttribute ("onclick", "setActiveStyleSheet('" + light + "')"); writer.RenderBeginTag("a"); writer.Write (light); writer.RenderEndTag (); //a writer.RenderEndTag (); //li writer.RenderEndTag (); //ul writer.RenderEndTag (); //div stylebox writer.RenderBeginTag ("div"); writer.Write (""); writer.Write (""); writer.Write ("" + Catalog.GetString ("Show Styles") + "" + Catalog.GetString ("Hide Styles") + "" + Environment.NewLine); writer.RenderEndTag (); //div toggle writer.RenderEndTag (); //div styleboxcontainer writer.RenderEndTag (); //container1 WriteFooter (writer); writer.RenderEndTag (); //body writer.RenderEndTag (); // html writer.Close (); stream.Close (); } public static string IndexPath (int page_num) { if (page_num == 0) return "index.html"; else return String.Format ("index{0}.html", page_num); } static string IndexTitle (int page) { return String.Format ("{0}", page + 1); } public void WriteHeader (System.Web.UI.HtmlTextWriter writer) { writer.RenderBeginTag ("head"); /* It seems HtmlTextWriter always uses UTF-8, unless told otherwise */ writer.Write (""); writer.WriteLine (); writer.RenderBeginTag ("title"); writer.Write (gallery_name); writer.RenderEndTag (); writer.Write ("" + Environment.NewLine); writer.Write ("" + Environment.NewLine); writer.Write ("" + Environment.NewLine); writer.RenderEndTag (); } public static void WriteFooter (System.Web.UI.HtmlTextWriter writer) { writer.AddAttribute ("class", "footer"); writer.RenderBeginTag ("div"); writer.Write (Catalog.GetString ("Gallery generated by") + " "); writer.AddAttribute ("href", "http://www.gnome.org/projects/f-spot"); writer.RenderBeginTag ("a"); writer.Write (String.Format ("{0} {1}", FSpot.Defines.PACKAGE, FSpot.Defines.VERSION)); writer.RenderEndTag (); writer.RenderEndTag (); } public void SaveHtmlIndex (int page_num) { System.IO.StreamWriter stream = System.IO.File.CreateText (SubdirPath (IndexPath (page_num))); System.Web.UI.HtmlTextWriter writer = new System.Web.UI.HtmlTextWriter (stream); //writer.Indent = 4; //writer.Write (""); writer.WriteLine (""); writer.AddAttribute ("xmlns", "http://www.w3.org/1999/xhtml"); writer.AddAttribute ("xml:lang", this.Language); writer.RenderBeginTag ("html"); WriteHeader (writer); writer.AddAttribute ("onload", "checkForTheme()"); writer.RenderBeginTag ("body"); writer.AddAttribute ("class", "container1"); writer.RenderBeginTag ("div"); writer.AddAttribute ("class", "header"); writer.RenderBeginTag ("div"); writer.AddAttribute ("id", "title"); writer.RenderBeginTag ("div"); writer.Write (gallery_name); writer.RenderEndTag (); //title div writer.AddAttribute ("class", "navi"); writer.RenderBeginTag ("div"); writer.AddAttribute ("class", "navilabel"); writer.RenderBeginTag ("div"); writer.Write (Catalog.GetString ("Page:")); writer.RenderEndTag (); //pages div int i; for (i = 0; i < PageCount; i++) { writer.AddAttribute ("class", i == page_num ? "navipage-current" : "navipage"); writer.RenderBeginTag ("div"); writer.AddAttribute ("href", IndexPath (i)); writer.RenderBeginTag ("a"); writer.Write (IndexTitle (i)); writer.RenderEndTag (); //a writer.RenderEndTag (); //navipage } writer.RenderEndTag (); //navi writer.RenderEndTag (); //header writer.AddAttribute ("class", "thumbs"); writer.RenderBeginTag ("div"); int start = page_num * perpage; int end = Math.Min (start + perpage, collection.Count); for (i = start; i < end; i++) { writer.AddAttribute ("href", PhotoIndexPath (i)); writer.RenderBeginTag ("a"); writer.AddAttribute ("src", PhotoThumbPath (i)); writer.AddAttribute ("alt", "#"); writer.RenderBeginTag ("img"); writer.RenderEndTag (); writer.RenderEndTag (); //a } writer.RenderEndTag (); //thumbs writer.AddAttribute ("id", "gallery_description"); writer.RenderBeginTag ("div"); writer.Write (description); writer.RenderEndTag (); //description //Style Selection Box writer.AddAttribute ("id", "styleboxcontainer"); writer.RenderBeginTag ("div"); writer.AddAttribute ("id", "stylebox"); writer.AddAttribute ("style", "display: none;"); writer.RenderBeginTag ("div"); writer.RenderBeginTag("ul"); writer.RenderBeginTag("li"); writer.AddAttribute ("href", "#"); writer.AddAttribute ("title", dark); writer.AddAttribute ("onclick", "setActiveStyleSheet('" + dark + "')"); writer.RenderBeginTag("a"); writer.Write (dark); writer.RenderEndTag (); //a writer.RenderEndTag (); //li writer.RenderBeginTag("li"); writer.AddAttribute ("href", "#"); writer.AddAttribute ("title", light); writer.AddAttribute ("onclick", "setActiveStyleSheet('" + light + "')"); writer.RenderBeginTag("a"); writer.Write (light); writer.RenderEndTag (); //a writer.RenderEndTag (); //li writer.RenderEndTag (); //ul writer.RenderEndTag (); //div stylebox writer.RenderBeginTag ("div"); writer.Write (""); writer.Write (""); writer.Write ("" + Catalog.GetString("Show Styles") + "" + Catalog.GetString("Hide Styles") + "" + Environment.NewLine); writer.RenderEndTag (); //div toggle writer.RenderEndTag (); //div styleboxcontainer writer.RenderEndTag (); //container1 WriteFooter (writer); writer.RenderEndTag (); //body writer.RenderEndTag (); //html writer.Close (); stream.Close (); } } }