[ease] Added a close confirmation dialog to the editor.



commit 605f71ea6a5d09db14706115a30e0d25099c4cef
Author: Nate Stedman <natesm gmail com>
Date:   Wed Jun 16 18:51:25 2010 -0400

    Added a close confirmation dialog to the editor.

 Makefile.am                        |    1 +
 src/ease-close-confirm-dialog.vala |  109 ++++++++++++++++++++++++++++++++++++
 src/ease-editor-window.vala        |  104 ++++++++++++++++++++++++-----------
 3 files changed, 182 insertions(+), 32 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index 2564928..975bc60 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -14,6 +14,7 @@ AM_CPPFLAGS = \
 ease_SOURCES = \
 	src/ease-about-dialog.vala \
 	src/ease-actor.vala \
+	src/ease-close-confirm-dialog.vala \
 	src/ease-document.vala \
 	src/ease-editor-embed.vala \
 	src/ease-editor-window.vala \
diff --git a/src/ease-close-confirm-dialog.vala b/src/ease-close-confirm-dialog.vala
new file mode 100644
index 0000000..1ddb59d
--- /dev/null
+++ b/src/ease-close-confirm-dialog.vala
@@ -0,0 +1,109 @@
+/*  Ease, a GTK presentation application
+    Copyright (C) 2010 Nate Stedman
+
+    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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+
+public class Ease.CloseConfirmDialog : Gtk.Dialog
+{
+	private const string TOP_FORMAT = "<b><big>%s</big></b>";
+	
+	public CloseConfirmDialog(string filename, int seconds)
+	{
+		title = _("Save before closing?");
+		has_separator = false;
+		
+		// dialog image
+		var image = new Gtk.Image.from_stock("gtk-dialog-warning",
+		                                     Gtk.IconSize.DIALOG);
+		image.set_alignment(0.5f, 0);
+		
+		// top label
+		var top_label = new Gtk.Label("");
+		top_label.wrap = true;
+		top_label.use_markup = true;
+		top_label.set_alignment(0, 0.5f);
+		top_label.selectable = true;
+		top_label.can_focus = false;
+		top_label.set_markup(TOP_FORMAT.printf(top_label_text(filename)));
+		
+		// bottom label
+		var bottom_label = new Gtk.Label(bottom_label_text(seconds));
+		bottom_label.wrap = true;
+		bottom_label.set_alignment(0, 0.5f);
+		bottom_label.set_selectable(true);
+		bottom_label.can_focus = false;
+		
+		// vbox for labels
+		var vbox = new Gtk.VBox(false, 12);
+		vbox.pack_start(top_label, false, false, 0);
+		vbox.pack_start(bottom_label, false, false, 0);
+		
+		// hbox for all top content
+		var hbox = new Gtk.HBox(false, 12);
+		hbox.set_border_width(5);
+		hbox.pack_start(image, false, false, 0);
+		hbox.pack_start(vbox, true, true, 0);
+		
+		(get_content_area() as Gtk.Box).pack_start(hbox, true, true, 0);
+		hbox.show_all();
+		
+		// buttons
+		add_buttons(_("Close _without Saving"), Gtk.ResponseType.NO,
+		            "gtk-cancel", Gtk.ResponseType.CANCEL,
+		            "gtk-save", Gtk.ResponseType.YES);
+		
+		set_default_response(Gtk.ResponseType.YES);
+	}
+	
+	private static string bottom_label_text(int seconds)
+	{
+		seconds = int.max(1, seconds);
+		
+		if (seconds < 55)
+		{
+			return ngettext("If you don't save, changes from the last second will be permanently lost.", "If you don't save, changes from the last %i seconds will be permanently lost.", seconds).printf(seconds);
+		}
+		if (seconds < 75)
+		{
+			return _("If you don't save, changes from the last minute will be permanently lost."); 
+		}
+		if (seconds < 110)
+		{
+			return ngettext("If you don't save, changes from the last minute and %i second will be permanently lost.", "If you don't save, changes from the last minute and %i seconds will be permanently lost.", seconds - 60).printf(seconds - 60);
+		}
+		if (seconds < 3600)
+		{
+			return ngettext("If you don't save, changes from the last %i minute will be permanently lost.", "If you don't save, changes from the last %i minutes will be permanently lost.", seconds / 60).printf(seconds / 60);
+		}
+		if (seconds < 7200)
+		{
+			int minutes = (seconds - 3600) / 60;
+			if (minutes < 5)
+			{
+				return _("If you don't save, changes from the last hour will be permanently lost.");
+			}
+			return ngettext("If you don't save, changes from the last hour and %i minute will be permanently lost.", "If you don't save, changes from the last hour and %i minutes will be permanently lost.", minutes).printf(minutes);
+		}
+		
+		int hours = seconds / 3600;
+		return ngettext("If you don't save, changes from the last %i hour will be permanently lost.", "If you don't save, changes from the last %i hours will be permanently lost.", hours).printf(hours);
+	}
+	
+	private static string top_label_text(string filename)
+	{
+		return (_("Save changes to \"%s\" before closing?")).printf(
+			filename);
+	}
+}
diff --git a/src/ease-editor-window.vala b/src/ease-editor-window.vala
index 8d5078d..99a0c26 100644
--- a/src/ease-editor-window.vala
+++ b/src/ease-editor-window.vala
@@ -82,6 +82,11 @@ public class Ease.EditorWindow : Gtk.Window
 	public bool slides_shown { get; set; }
 	
 	/**
+	 * The time the document was last saved.
+	 */
+	long last_saved = 0;
+	
+	/**
 	 * The zoom levels for the { link ZoomSlider}
 	 */
 	private int[] ZOOM_LEVELS = {10, 25, 33, 50, 66, 75, 100, 125, 150,
@@ -139,6 +144,25 @@ public class Ease.EditorWindow : Gtk.Window
 		
 		// USER INTERFACE SIGNALS
 		
+		// close the window
+		delete_event.connect((sender, event) => {
+			if (last_saved == 0) return false;
+			
+			var name = document.filename == null ? _("Untitled Document") :
+			                                       document.filename;
+			var time_diff = (int)(time_t() - last_saved);
+			
+			var dialog = new CloseConfirmDialog(name, time_diff);
+			var response = dialog.run();
+			dialog.destroy();
+			
+			if (response == Gtk.ResponseType.CANCEL) return true;
+			if (response == Gtk.ResponseType.NO) return false;
+			
+			// otherwise, save and quit
+			return !save_document();
+		});
+		
 		// toolbar
 		
 		// create new slides
@@ -189,38 +213,7 @@ public class Ease.EditorWindow : Gtk.Window
 		
 		// save file
 		main_toolbar.save.clicked.connect(() => {
-			if (document.filename == null)
-			{
-				var dialog =
-					new Gtk.FileChooserDialog(_("Save Document"),
-		        	                          null,
-		        	                          Gtk.FileChooserAction.SAVE,
-		        	                          "gtk-cancel",
-		        	                          Gtk.ResponseType.CANCEL,
-		        	                          "gtk-open",
-		        	                          Gtk.ResponseType.ACCEPT, null);
-		        
-		        var filter = new Gtk.FileFilter();
-				filter.add_pattern("*.ease");
-				dialog.filter = filter;
-
-				if (dialog.run() == Gtk.ResponseType.ACCEPT)
-				{
-					document.filename = dialog.get_filename();
-				}
-				else
-				{
-					dialog.destroy();
-					return;
-				}
-				dialog.destroy();
-			}
-		
-			try { JSONParser.document_write(document); }
-			catch (GLib.Error e)
-			{
-				error_dialog(_("Error Saving Document"), e.message);
-			}
+			save_document();
 		});
 		
 		// play presentation
@@ -287,6 +280,12 @@ public class Ease.EditorWindow : Gtk.Window
 		undo.add_action(action);
 		undo.clear_redo();
 		update_undo();
+		
+		// the document has been edited, first change at this time
+		if (last_saved == 0)
+		{
+			last_saved = time_t();
+		}
 	}
 	
 	/**
@@ -300,6 +299,47 @@ public class Ease.EditorWindow : Gtk.Window
 	}
 	
 	// signal handlers
+	private bool save_document()
+	{
+		if (document.filename == null)
+		{
+			var dialog =
+				new Gtk.FileChooserDialog(_("Save Document"),
+	        	                          null,
+	        	                          Gtk.FileChooserAction.SAVE,
+	        	                          "gtk-cancel",
+	        	                          Gtk.ResponseType.CANCEL,
+	        	                          "gtk-save",
+	        	                          Gtk.ResponseType.ACCEPT, null);
+	        
+	        var filter = new Gtk.FileFilter();
+			filter.add_pattern("*.ease");
+			dialog.filter = filter;
+
+			if (dialog.run() == Gtk.ResponseType.ACCEPT)
+			{
+				document.filename = dialog.get_filename();
+			}
+			else
+			{
+				dialog.destroy();
+				return false;
+			}
+			dialog.destroy();
+		}
+	
+		try
+		{
+			JSONParser.document_write(document);
+			last_saved = 0;
+		}
+		catch (GLib.Error e)
+		{
+			error_dialog(_("Error Saving Document"), e.message);
+			return false;
+		}
+		return true;
+	}
 	
 	// menu bar creation
 	private Gtk.MenuBar create_menu_bar()



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