[tasque/transition: 92/213] Update Gtk single app instance logic
- From: Antonius Riha <antoniusri src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [tasque/transition: 92/213] Update Gtk single app instance logic
- Date: Wed, 29 Aug 2012 18:41:45 +0000 (UTC)
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]