[tasque/transition: 92/213] Update Gtk single app instance logic



commit dc127232969b7230cb1d9a9dd1f3f524f1d47e82
Author: Antonius Riha <antoniusriha gmail com>
Date:   Sun Jul 29 02:02:21 2012 +0200

    Update Gtk single app instance logic
    
    * Moved the single app instance logic from Application.cs
    to GtkApplication.cs
    * The single instance logic makes now use of the new programming model
    in NativeApplication.cs - the IsRemoteInstanceRunning mehtod and the
    RemoteInstanceKnocked event.
    * RemoteControl.cs: remove lots of stuff that is not used anywhere
    * RemoteControlProxy.cs: merge static methods into RemoteControl.cs
    and remove RemoteControlProxy.cs

 src/Tasque.Gtk/Application.cs        |   29 +--
 src/Tasque.Gtk/GtkApplication.cs     |   56 ++++-
 src/Tasque.Gtk/RemoteControl.cs      |  468 ++++------------------------------
 src/Tasque.Gtk/RemoteControlProxy.cs |   36 ---
 src/Tasque.Gtk/Tasque.Gtk.csproj     |    1 -
 src/libtasque/NativeApplication.cs   |   18 ++-
 6 files changed, 121 insertions(+), 487 deletions(-)
---
diff --git a/src/Tasque.Gtk/Application.cs b/src/Tasque.Gtk/Application.cs
index b9f45e7..d7d3789 100644
--- a/src/Tasque.Gtk/Application.cs
+++ b/src/Tasque.Gtk/Application.cs
@@ -55,9 +55,7 @@ namespace Tasque
 		private static Tasque.Application application = null;
 		private static System.Object locker = new System.Object();
 		private NativeApplication nativeApp;
-#if !WIN32
-		private RemoteControl remoteControl;
-#endif
+
 		private Gtk.StatusIcon trayIcon;	
 		private Preferences preferences;
 		private Backend backend;
@@ -162,30 +160,7 @@ namespace Tasque
 
 			preferences = new Preferences (nativeApp.ConfDir);
 			
-#if !WIN32
-			// Register Tasque RemoteControl
-			try {
-				remoteControl = RemoteControlProxy.Register ();
-				if (remoteControl != null) {
-					Debug.Write ("Tasque remote control active.");
-				} else {
-					// If Tasque is already running, open the tasks window
-					// so the user gets some sort of feedback when they
-					// attempt to run Tasque again.
-					RemoteControl remote = null;
-					try {
-						remote = RemoteControlProxy.GetInstance ();
-						remote.ShowTasks ();
-					} catch {}
-
-					Debug.WriteLine ("Tasque is already running.  Exiting...");
-					System.Environment.Exit (0);
-				}
-			} catch (Exception e) {
-				Debug.WriteLine ("Tasque remote control disabled (DBus exception): {0}",
-				            e.Message);
-			}
-#endif
+
 			
 			string potentialBackendClassName = null;
 			
diff --git a/src/Tasque.Gtk/GtkApplication.cs b/src/Tasque.Gtk/GtkApplication.cs
index f2293e9..8eaea57 100644
--- a/src/Tasque.Gtk/GtkApplication.cs
+++ b/src/Tasque.Gtk/GtkApplication.cs
@@ -46,7 +46,8 @@ namespace Tasque
 
 		public override void Initialize (string[] args)
 		{
-			Catalog.Init ("tasque", GlobalDefines.LocaleDir);
+			base.Initialize (args);
+//			Catalog.Init ("tasque", GlobalDefines.LocaleDir);
 			Gtk.Application.Init ();
 		}
 		
@@ -68,7 +69,60 @@ namespace Tasque
 				Trace.TraceError ("Error opening url [{0}]:\n{1}", url, e.ToString ());
 			}
 		}
+		
+		protected override bool IsRemoteInstanceRunning ()
+		{
+#if !WIN32
+			// Register Tasque RemoteControl
+			try {
+				remoteInstance = RemoteControl.Register ();
+				if (remoteInstance != null) {
+					remoteInstance.RemoteInstanceKnocked = HandleRemoteInstanceKnocked;
+					Debug.Write ("Tasque remote control active.");
+				} else {
+					// If Tasque is already running, open the tasks window
+					// so the user gets some sort of feedback when they
+					// attempt to run Tasque again.
+					RemoteControl remote = null;
+					try {
+						remote = RemoteControl.GetInstance ();
+						remote.KnockKnock ();
+					} catch {}
+
+					Debug.WriteLine ("Tasque is already running.  Exiting...");
+					return true;
+				}
+			} catch (Exception e) {
+				Debug.WriteLine ("Tasque remote control disabled (DBus exception): {0}", e.Message);
+			}
+			return false;
+#else
+			
+#endif
+		}
+
+		protected override void ShowMainWindow ()
+		{
+			TaskWindow.ShowWindow ();
+		}
+		
+		protected override event EventHandler RemoteInstanceKnocked;
+		
+		void HandleRemoteInstanceKnocked ()
+		{
+			if (RemoteInstanceKnocked != null)
+				RemoteInstanceKnocked (this, EventArgs.Empty);
+		}
+		
+		protected override void Dispose (bool disposing)
+		{
+			if (disposing)
+				remoteInstance.RemoteInstanceKnocked = null;
+		}
 
 		string confDir;
+#if !WIN32
+		RemoteControl remoteInstance;
+#endif
 	}
 }
diff --git a/src/Tasque.Gtk/RemoteControl.cs b/src/Tasque.Gtk/RemoteControl.cs
index bd4cada..f574c3e 100644
--- a/src/Tasque.Gtk/RemoteControl.cs
+++ b/src/Tasque.Gtk/RemoteControl.cs
@@ -1,449 +1,75 @@
 // RemoteControl.cs created with MonoDevelop
-// User: sandy at 9:49 AMÂ2/14/2008
+// User: sandy at 9:49 AM 2/14/2008
 //
 // To change standard headers go to Edit->Preferences->Coding->Standard Headers
 //
-
+// RemoteControl.cs
+//  
+// Author:
+//       Antonius Riha <antoniusriha gmail com>
+// 
+// Copyright (c) 2012 Antonius Riha
+// 
+// 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;
-using System.Collections.Generic;
-using System.Linq;
-
-using Mono.Unix; // for Catalog.GetString ()
-
-#if ENABLE_NOTIFY_SHARP
-using Notifications;
-#endif
-
-using org.freedesktop.DBus;
 using NDesk.DBus;
+using org.freedesktop.DBus;
 
 namespace Tasque
 {
 	[Interface ("org.gnome.Tasque.RemoteControl")]
 	public class RemoteControl : MarshalByRefObject
 	{
-		static Gdk.Pixbuf tasqueIcon;
-		static RemoteControl ()
+		public static RemoteControl GetInstance ()
 		{
-			tasqueIcon = Utilities.GetIcon ("tasque-48", 48);
-		}
-		
-		public RemoteControl()
-		{
-		}
-				
-		/// <summary>
-		/// Create a new task in Tasque using the given categoryName and name.
-		/// Will not attempt to parse due date information.
-		/// </summary>
-		/// <param name="categoryName">
-		/// A <see cref="System.String"/>.  The name of an existing category.
-		/// Matches are not case-sensitive.
-		/// </param>
-		/// <param name="taskName">
-		/// A <see cref="System.String"/>.  The name of the task to be created.
-		/// </param>
-		/// <param name="enterEditMode">
-		/// A <see cref="System.Boolean"/>.  Specify true if the TaskWindow
-		/// should be shown, the new task scrolled to, and have it be put into
-		/// edit mode immediately.
-		/// </param>
-		/// <returns>
-		/// A unique <see cref="System.String"/> which can be used to reference
-		/// the task later.
-		/// </returns>
-		public string CreateTask (string categoryName, string taskName,
-						bool enterEditMode)
-		{
-			return CreateTask (categoryName, taskName, enterEditMode, false);
-		}
+			BusG.Init ();
 
-		/// <summary>
-		/// Create a new task in Tasque using the given categoryName and name.
-		/// </summary>
-		/// <param name="categoryName">
-		/// A <see cref="System.String"/>.  The name of an existing category.
-		/// Matches are not case-sensitive.
-		/// </param>
-		/// <param name="taskName">
-		/// A <see cref="System.String"/>.  The name of the task to be created.
-		/// </param>
-		/// <param name="enterEditMode">
-		/// A <see cref="System.Boolean"/>.  Specify true if the TaskWindow
-		/// should be shown, the new task scrolled to, and have it be put into
-		/// edit mode immediately.
-		/// </param>
-		/// <param name="parseDate">
-		/// A <see cref="System.Boolean"/>.  Specify true if the 
-		/// date should be parsed out of the taskName (in case 
-		/// Preferences.ParseDateEnabledKey is true as well).
-		/// </param>
-		/// <returns>
-		/// A unique <see cref="System.String"/> which can be used to reference
-		/// the task later.
-		/// </returns>
-		public string CreateTask (string categoryName, string taskName,
-						bool enterEditMode, bool parseDate)
-		{
-			var categories = Application.Backend.Categories2;
-			
-			//
-			// Validate the input parameters.  Don't allow null or empty strings
-			// be passed-in.
-			//
-			if (string.IsNullOrWhiteSpace (categoryName) || string.IsNullOrWhiteSpace (taskName))
-				return string.Empty;
-			
-			//
-			// Look for the specified category
-			//
-			Category category = null;
-			categories.SingleOrDefault (c => c.Name.ToLower () == categoryName.ToLower ());
-			
-			if (category == null)
-				return string.Empty;
-			
-			// If enabled, attempt to parse due date information
-			// out of the taskName.
-			DateTime taskDueDate = DateTime.MinValue;
-			if (parseDate && Application.Preferences.GetBool (Preferences.ParseDateEnabledKey))
-				TaskParser.Instance.TryParse (
-				                         taskName,
-				                         out taskName,
-				                         out taskDueDate);
-			Task task = null;
-			try {
-				task = Application.Backend.CreateTask (taskName, category);
-				if (taskDueDate != DateTime.MinValue)
-					task.DueDate = taskDueDate;
-			} catch (Exception e) {
-				Trace.TraceError ("Exception calling Application.Backend.CreateTask from RemoteControl: {0}", e.Message);
-				return string.Empty;
-			}
-			
-			if (task == null) {
-				return string.Empty;
-			}
-			
-			if (enterEditMode) {
-				TaskWindow.SelectAndEdit (task);
-			}
-			
-			#if ENABLE_NOTIFY_SHARP
-			// Use notify-sharp to alert the user that a new task has been
-			// created successfully.
-			Notification notify =
-				new Notification (
-					Catalog.GetString ("New task created."), // summary
-					Catalog.GetString (taskName), // body
-					tasqueIcon);
-			Application.ShowAppNotification (notify);
-			#endif
-			
-			
-			return task.Id;
-		}
-		
-		/// <summary>
-		/// Return an array of Category names.
-		/// </summary>
-		/// <returns>
-		/// A <see cref="System.String"/>
-		/// </returns>
-		public string[] GetCategoryNames ()
-		{
-			List<string> categories = new List<string> ();
-			var model = Application.Backend.Categories;
-			
-			foreach (var item in model) {
-				if (item is AllCategory)
-					continue;
-				
-				categories.Add (((Category)item).Name);
-			}
-			
-			return categories.ToArray ();
-		}
-		
-		public void ShowTasks ()
-		{
-			TaskWindow.ShowWindow ();
+			if (!Bus.Session.NameHasOwner (Namespace))
+				Bus.Session.StartServiceByName (Namespace);
+
+			return Bus.Session.GetObject<RemoteControl> (Namespace, new ObjectPath (Path));
 		}
-		
-		/// <summary>
-		/// Retreives the IDs of all tasks for the current backend.
-		/// </summary>
-		/// <returns>
-		/// A <see cref="System.String"/> array containing the ID of all tasks
-		/// in the current backend.
-		/// </returns>
-		public string[] GetTaskIds ()
-		{
-			var model = Application.Backend.Tasks2;
 
-			if (model == null)
-				return new string[0];
+		public static RemoteControl Register ()
+		{
+			BusG.Init ();
 
-			List<string> ids = new List<string> ();
-			foreach (var task in model) {
-				ids.Add (task.Id);
-			}
+			var remoteControl = new RemoteControl ();
+			Bus.Session.Register (new ObjectPath (Path), remoteControl);
 
-			return ids.ToArray ();
+			if (Bus.Session.RequestName (Namespace) != RequestNameReply.PrimaryOwner)
+				return null;
 
+			return remoteControl;
 		}
 		
-		/// <summary>
-		/// Gets the name of a task for a given ID
-		/// </summary>
-		/// <param name="id">
-		/// A <see cref="System.String"/> for the ID of the task
-		/// </param>
-		/// <returns>
-		/// A <see cref="System.String"/> the name of the task
-		/// </returns>
-		public string GetNameForTaskById (string id)
-		{
-			Task task = GetTaskById (id);
-			return task != null ? task.Name : string.Empty;
-		}
+		RemoteControl () {}
 		
-		/// <summary>
-		/// Sets the name of a task for a given ID
-		/// </summary>
-		/// <param name="id">
-		/// A <see cref="System.String"/> for the ID of the task
-		/// </param>
-		/// <param>
-		/// A <see cref="System.String"/> the name of the task
-		/// </param>
-		/// <returns>
-		/// A <see cref="System.Boolean"/>, true for success, false
-		/// for failure.
-		/// </returns>
-		public bool SetNameForTaskById (string id, string name)
+		public void KnockKnock ()
 		{
-			Task task = GetTaskById (id);
-			if (task == null)
-			{
-				return false;
-			}
-			task.Name = name;
-			return true;
+			if (RemoteInstanceKnocked != null)
+				RemoteInstanceKnocked ();
 		}
 		
-		/// <summary>
-		/// Gets the category of a task for a given ID
-		/// </summary>
-		/// <param name="id">
-		/// A <see cref="System.String"/> for the ID of the task
-		/// </param>
-		/// <returns>
-		/// A <see cref="System.String"/> the category of the task
-		/// </returns>
-		public string GetCategoryForTaskById (string id)
-		{
-			Task task = GetTaskById (id);
-			return task != null ? task.Category.Name : string.Empty;
-		}
+		public Action RemoteInstanceKnocked { get; set; }
 		
-		/// <summary>
-		/// Sets the category of a task for a given ID
-		/// </summary>
-		/// <param name="id">
-		/// A <see cref="System.String"/> for the ID of the task
-		/// </param>
-		/// <param name="category">
-		/// A <see cref="System.String"/> the category of the task
-		/// </param>
-		/// <returns>
-		/// A <see cref="System.Boolean"/>, true for success, false
-		/// for failure.
-		/// </returns>
-		public bool SetCategoryForTaskById (string id, string categoryName)
-		{
-			Task task = GetTaskById (id);
-			if (task == null)
-				return false;
-			
-			var categories = Application.Backend.Categories2;
-			return categories.Contains (task.Category);
-		}
-		
-		/// <summary>
-		/// Get the due date of a task for a given ID
-		/// </summary>
-		/// <param name="id">
-		/// A <see cref="System.String"/> for the ID of the task
-		/// </param>
-		/// <returns>
-		/// A <see cref="System.Int32"/> containing the POSIX time
-		/// of the due date
-		/// </returns>
-		public int GetDueDateForTaskById (string id)
-		{
-			Task task = GetTaskById (id);
-			if (task == null)
-				return -1;
-			if (task.DueDate == DateTime.MinValue)
-				return 0;
-			return (int)(task.DueDate - new DateTime(1970,1,1)).TotalSeconds;
-		}
-		
-		/// <summary>
-		/// Set the due date of a task for a given ID
-		/// </summary>
-		/// <param name="id">
-		/// A <see cref="System.String"/> for the ID of the task
-		/// </param>
-		/// <param name="duedate">
-		/// A <see cref="System.Int32"/> containing the POSIX time
-		/// of the due date
-		/// </param>
-		/// <returns>
-		/// A <see cref="System.Boolean"/>, true for success, false
-		/// for failure.
-		/// <returns>
-		public bool SetDueDateForTaskById (string id, int dueDate)
-		{
-			Task task = GetTaskById (id);
-			if (task == null)
-			{
-				return false;
-			}
-			if (dueDate == 0)
-				task.DueDate = DateTime.MinValue;
-			else
-				task.DueDate = new DateTime(1970,1,1).AddSeconds(dueDate);
-			return true;
-		}
-		
-		/// <summary>
-		/// Gets the state of a task for a given ID
-		/// </summary>
-		/// <param name="id">
-		/// A <see cref="System.String"/> for the ID of the task
-		/// </param>
-		/// <returns>
-		/// A <see cref="System.Int32"/> the state of the task
-		/// </returns>
-		public int GetStateForTaskById (string id)
-		{
-			Task task = GetTaskById (id);
-			return task != null ? (int) task.State : -1;
-		}
-
-		/// <summary>
-		/// Gets the priority of a task for a given ID
-		/// </summary>
-		/// <param name="id">
-		/// A <see cref="System.String"/> for the ID of the task
-		/// </param>
-		/// <returns>
-		/// A <see cref="System.Int32"/> the priority of the task
-		/// </returns>
-		public int GetPriorityForTaskById (string id)
-		{
-			Task task = GetTaskById (id);
-			return task != null ? (int) task.Priority : -1;
-		}
-		
-		/// <summary>
-		/// Sets the priority of a task for a given ID
-		/// </summary>
-		/// <param name="id">
-		/// A <see cref="System.String"/> for the ID of the task
-		/// </param>
-		/// <param name="priority">
-		/// A <see cref="System.Int32"/> the priority of the task
-		/// </param>
-		/// <returns>
-		/// A <see cref="System.Boolean"/>, true for success, false
-		/// for failure.
-		/// </returns>
-		public bool SetPriorityForTaskById (string id, int priority)
-		{
-			Task task = GetTaskById (id);
-			if (task == null)
-			{
-				return false;
-			}
-			task.Priority = (TaskPriority) priority;
-			return true;
-		}
-		
-		/// <summary>
-		/// Marks a task active
-		/// </summary>
-		/// <param name="id">
-		/// A <see cref="System.String"/> for the ID of the task
-		/// </param>
-		/// <returns>
-		/// A <see cref="System.Boolean"/>, true for success, false
-		/// for failure.
-		/// </returns>
-		public bool MarkTaskAsActiveById (string id)
-		{
-			Task task = GetTaskById (id);
-			if (task == null)
-				return false;
-				
-			task.Activate ();
-			return true;
-		}
-		
-		/// <summary>
-		/// Marks a task complete
-		/// </summary>
-		/// <param name="id">
-		/// A <see cref="System.String"/> for the ID of the task
-		/// </param>
-		public void MarkTaskAsCompleteById (string id)
-		{
-			Task task = GetTaskById (id);
-			if (task == null)
-				return;
-				
-			if (task.State == TaskState.Active) {
-				// Complete immediately; no timeout or fancy
-				// GUI stuff.
-				task.Complete ();
-			}
-		}
-		
-		/// <summary>
-		/// Deletes a task
-		/// </summary>
-		/// <param name="id">
-		/// A <see cref="System.String"/> for the ID of the task
-		/// </param>
-		/// <returns>
-		/// A <see cref="System.Boolean"/>, true for sucess, false
-		/// for failure.
-		/// </returns>
-		public bool DeleteTaskById (string id)
-		{
-			Task task = GetTaskById (id);
-			if (task == null)
-				return false;
-				
-			task.Delete ();
-			return true;
-		}
-
-		
-		/// <summary>
-		/// Looks up a task by ID in the backend
-		/// </summary>
-		/// <param name="id">
-		/// A <see cref="System.String"/> for the ID of the task
-		/// </param>
-		/// <returns>
-		/// A <see cref="ITask"/> having the given ID
-		/// </returns>
-		private Task GetTaskById (string id)
-		{
-			return Application.Backend.Tasks2.SingleOrDefault (f => f.Id == id);
-		}
+		const string Namespace = "org.gnome.Tasque";
+		const string Path = "/org/gnome/Tasque/RemoteControl";
 	}
 }
diff --git a/src/Tasque.Gtk/Tasque.Gtk.csproj b/src/Tasque.Gtk/Tasque.Gtk.csproj
index aadc3fd..1fe780d 100644
--- a/src/Tasque.Gtk/Tasque.Gtk.csproj
+++ b/src/Tasque.Gtk/Tasque.Gtk.csproj
@@ -128,7 +128,6 @@
   </ItemGroup>
   <ItemGroup Condition=" '$(Configuration)' == 'GtkLinuxDebug' or '$(Configuration)' == 'GtkLinuxRelease' ">
     <Compile Include="RemoteControl.cs" />
-    <Compile Include="RemoteControlProxy.cs" />
   </ItemGroup>
   <ItemGroup>
     <Folder Include="Properties\" />
diff --git a/src/libtasque/NativeApplication.cs b/src/libtasque/NativeApplication.cs
index 66544a8..e894d04 100644
--- a/src/libtasque/NativeApplication.cs
+++ b/src/libtasque/NativeApplication.cs
@@ -42,7 +42,15 @@ namespace Tasque
 			Environment.Exit (exitcode);
 		}
 
-		public abstract void Initialize (string[] args);
+		public virtual void Initialize (string[] args)
+		{
+			if (IsRemoteInstanceRunning ()) {
+				Trace.TraceInformation ("Another instance of Tasque is already running.");
+				Exit (0);
+			}
+			
+			RemoteInstanceKnocked += delegate { ShowMainWindow (); };
+		}
 
 		public virtual void InitializeIdle () {}
 
@@ -59,6 +67,14 @@ namespace Tasque
 
 		public event EventHandler Exiting;
 
+		//DOCS: Tasque is a single instance app. If Tasque is already started in the current user's
+		// domain, don't start it again. Returns null if no instance found
+		protected abstract bool IsRemoteInstanceRunning ();
+
+		protected abstract void ShowMainWindow ();
+		
+		protected abstract event EventHandler RemoteInstanceKnocked;
+		
 		#region IDisposable implementation
 		public void Dispose ()
 		{



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