[tasque] Remove Inactivate task state and outsource timer treeview col
- From: Antonius Riha <antoniusri src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [tasque] Remove Inactivate task state and outsource timer treeview col
- Date: Sat, 19 Jan 2013 20:27:19 +0000 (UTC)
commit abfa2f8197f212936b68e338b294c5a1217ff6a0
Author: Antonius Riha <antoniusriha gmail com>
Date: Sun Jan 6 22:46:50 2013 +0100
Remove Inactivate task state and outsource timer treeview col
src/Addins/Backends/Dummy/DummyTask.cs | 7 -
src/Addins/Backends/Rtm/RtmTask.cs | 10 -
src/Addins/Backends/Sqlite/SqliteTask.cs | 7 -
src/Gtk.Tasque/AppIndicatorTray.cs | 3 +-
src/Gtk.Tasque/Gtk.Tasque.csproj | 1 +
src/Gtk.Tasque/GtkApplicationBase.cs | 3 +-
src/Gtk.Tasque/GtkLinuxApplication.cs | 3 +-
src/Gtk.Tasque/GtkTray.cs | 5 +-
src/Gtk.Tasque/ITaskField.cs | 36 ++++
src/Gtk.Tasque/RemoteControl.cs | 5 +-
src/Gtk.Tasque/StatusIconTray.cs | 3 +-
src/Gtk.Tasque/TaskTreeView.cs | 317 ++++--------------------------
src/Gtk.Tasque/TaskWindow.cs | 6 +-
src/Gtk.Tasque/TimerColumn.cs | 317 ++++++++++++++++++++++++++++++
src/Gtk.Tasque/TimerTaskField.cs | 44 ++++
src/libtasque/AbstractTask.cs | 1 -
src/libtasque/ITask.cs | 7 +-
src/libtasque/TaskGroupModel.cs | 5 -
src/libtasque/TaskState.cs | 7 -
src/tasque/Program.cs | 1 +
20 files changed, 451 insertions(+), 337 deletions(-)
---
diff --git a/src/Addins/Backends/Dummy/DummyTask.cs b/src/Addins/Backends/Dummy/DummyTask.cs
index 5d51199..83d979d 100644
--- a/src/Addins/Backends/Dummy/DummyTask.cs
+++ b/src/Addins/Backends/Dummy/DummyTask.cs
@@ -133,13 +133,6 @@ Logger.Debug ("DummyTask.Activate ()");
CompletionDate = DateTime.MinValue;
}
- public override void Inactivate ()
- {
-Logger.Debug ("DummyTask.Inactivate ()");
- state = TaskState.Inactive;
- CompletionDate = DateTime.Now;
- }
-
public override void Complete ()
{
Logger.Debug ("DummyTask.Complete ()");
diff --git a/src/Addins/Backends/Rtm/RtmTask.cs b/src/Addins/Backends/Rtm/RtmTask.cs
index d6bb74f..c36b707 100644
--- a/src/Addins/Backends/Rtm/RtmTask.cs
+++ b/src/Addins/Backends/Rtm/RtmTask.cs
@@ -252,16 +252,6 @@ namespace Tasque.Backends.Rtm
}
/// <summary>
- /// Sets the task to be inactive
- /// </summary>
- public override void Inactivate ()
- {
- Logger.Debug("Inactivating Task: " + Name);
- state = TaskState.Inactive;
- CompletionDate = DateTime.Now;
- }
-
- /// <summary>
/// Completes the task
/// </summary>
public override void Complete ()
diff --git a/src/Addins/Backends/Sqlite/SqliteTask.cs b/src/Addins/Backends/Sqlite/SqliteTask.cs
index d262fd7..c12c8a5 100644
--- a/src/Addins/Backends/Sqlite/SqliteTask.cs
+++ b/src/Addins/Backends/Sqlite/SqliteTask.cs
@@ -191,13 +191,6 @@ namespace Tasque.Backends.Sqlite
CompletionDate = DateTime.MinValue;
}
- public override void Inactivate ()
- {
- // Logger.Debug ("SqliteTask.Inactivate ()");
- LocalState = TaskState.Inactive;
- CompletionDate = DateTime.Now;
- }
-
public override void Complete ()
{
//Logger.Debug ("SqliteTask.Complete ()");
diff --git a/src/Gtk.Tasque/AppIndicatorTray.cs b/src/Gtk.Tasque/AppIndicatorTray.cs
index d724345..e561d2d 100644
--- a/src/Gtk.Tasque/AppIndicatorTray.cs
+++ b/src/Gtk.Tasque/AppIndicatorTray.cs
@@ -23,10 +23,11 @@
// 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 Tasque;
using Gtk;
using AppIndicator;
-namespace Tasque
+namespace Gtk.Tasque
{
public class AppIndicatorTray : GtkTray
{
diff --git a/src/Gtk.Tasque/Gtk.Tasque.csproj b/src/Gtk.Tasque/Gtk.Tasque.csproj
index 17b6fe6..d2376f7 100644
--- a/src/Gtk.Tasque/Gtk.Tasque.csproj
+++ b/src/Gtk.Tasque/Gtk.Tasque.csproj
@@ -105,6 +105,7 @@
<Compile Include="GtkLinuxApplication.cs" />
<Compile Include="GtkWinApplication.cs" />
<Compile Include="TreeModelListAdapter.cs" />
+ <Compile Include="TimerColumn.cs" />
</ItemGroup>
<ItemGroup Condition=" '$(Configuration)' == 'LinuxDebug' Or '$(Configuration)' == 'LinuxRelease' ">
<Compile Include="RemoteControl.cs" />
diff --git a/src/Gtk.Tasque/GtkApplicationBase.cs b/src/Gtk.Tasque/GtkApplicationBase.cs
index 7c7004f..879031c 100644
--- a/src/Gtk.Tasque/GtkApplicationBase.cs
+++ b/src/Gtk.Tasque/GtkApplicationBase.cs
@@ -28,12 +28,13 @@ using System;
using System.Diagnostics;
using System.IO;
using Mono.Unix;
+using Tasque;
using Gtk;
#if ENABLE_NOTIFY_SHARP
using Notifications;
#endif
-namespace Tasque
+namespace Gtk.Tasque
{
public abstract class GtkApplicationBase : NativeApplication
{
diff --git a/src/Gtk.Tasque/GtkLinuxApplication.cs b/src/Gtk.Tasque/GtkLinuxApplication.cs
index 3157f0c..a2e7403 100644
--- a/src/Gtk.Tasque/GtkLinuxApplication.cs
+++ b/src/Gtk.Tasque/GtkLinuxApplication.cs
@@ -25,8 +25,9 @@
// THE SOFTWARE.
#if LINUX
using System;
+using Tasque;
-namespace Tasque
+namespace Gtk.Tasque
{
public class GtkLinuxApplication : GtkApplicationBase
{
diff --git a/src/Gtk.Tasque/GtkTray.cs b/src/Gtk.Tasque/GtkTray.cs
index 71a66c5..f4f4ba3 100644
--- a/src/Gtk.Tasque/GtkTray.cs
+++ b/src/Gtk.Tasque/GtkTray.cs
@@ -27,10 +27,11 @@ using System;
using System.Linq;
using System.Text;
using Mono.Unix;
-using Gtk;
+using Tasque;
using Tasque.Backends;
+using Gtk;
-namespace Tasque
+namespace Gtk.Tasque
{
public abstract class GtkTray : IDisposable
{
diff --git a/src/Gtk.Tasque/ITaskField.cs b/src/Gtk.Tasque/ITaskField.cs
new file mode 100644
index 0000000..b879136
--- /dev/null
+++ b/src/Gtk.Tasque/ITaskField.cs
@@ -0,0 +1,36 @@
+//
+// ITaskColumn.cs
+//
+// Author:
+// Antonius Riha <antoniusriha gmail com>
+//
+// Copyright (c) 2013 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 Tasque;
+
+namespace Gtk.Tasque
+{
+ public interface ITaskField
+ {
+ string HeaderText { get; set; }
+ void Initialize (ITask task);
+ }
+}
diff --git a/src/Gtk.Tasque/RemoteControl.cs b/src/Gtk.Tasque/RemoteControl.cs
index 8553c65..347279e 100644
--- a/src/Gtk.Tasque/RemoteControl.cs
+++ b/src/Gtk.Tasque/RemoteControl.cs
@@ -9,6 +9,7 @@ using System.Collections.Generic;
using System.Linq;
using Mono.Unix; // for Catalog.GetString ()
+using Tasque;
#if ENABLE_NOTIFY_SHARP
using Notifications;
@@ -17,7 +18,7 @@ using Notifications;
using org.freedesktop.DBus;
using DBus;
-namespace Tasque
+namespace Gtk.Tasque
{
[Interface ("org.gnome.Tasque.RemoteControl")]
public class RemoteControl : MarshalByRefObject
@@ -61,7 +62,7 @@ namespace Tasque
RemoteInstanceKnocked ();
}
- public Action RemoteInstanceKnocked { get; set; }
+ public System.Action RemoteInstanceKnocked { get; set; }
/// <summary>
/// Create a new task in Tasque using the given categoryName and name.
diff --git a/src/Gtk.Tasque/StatusIconTray.cs b/src/Gtk.Tasque/StatusIconTray.cs
index d379889..12e329d 100644
--- a/src/Gtk.Tasque/StatusIconTray.cs
+++ b/src/Gtk.Tasque/StatusIconTray.cs
@@ -23,9 +23,10 @@
// 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 Tasque;
using Gtk;
-namespace Tasque
+namespace Gtk.Tasque
{
public class StatusIconTray : GtkTray
{
diff --git a/src/Gtk.Tasque/TaskTreeView.cs b/src/Gtk.Tasque/TaskTreeView.cs
index a0f39d6..b6b87cc 100644
--- a/src/Gtk.Tasque/TaskTreeView.cs
+++ b/src/Gtk.Tasque/TaskTreeView.cs
@@ -3,10 +3,11 @@
using System;
using System.Collections.Generic;
-using Gtk;
using Mono.Unix;
+using Tasque;
+using Gtk;
-namespace Tasque
+namespace Gtk.Tasque
{
/// <summary>
/// This is the main TreeView widget that is used to show tasks in Tasque's
@@ -16,10 +17,10 @@ namespace Tasque
{
IPreferences preferences;
+ TimerColumn timerCol;
+
private static Gdk.Pixbuf notePixbuf;
- private static Gdk.Pixbuf[] inactiveAnimPixbufs;
-
private Gtk.TreeModelFilter modelFilter;
private ICategory filterCategory;
private ITask taskBeingEdited = null;
@@ -29,12 +30,6 @@ namespace Tasque
static TaskTreeView ()
{
notePixbuf = Utilities.GetIcon ("tasque-note", 12);
-
- inactiveAnimPixbufs = new Gdk.Pixbuf [12];
- for (int i = 0; i < 12; i++) {
- string iconName = string.Format ("tasque-completing-{0}", i);
- inactiveAnimPixbufs [i] = Utilities.GetIcon (iconName, 16);
- }
}
public event EventHandler NumberOfTasksChanged;
@@ -242,20 +237,17 @@ namespace Tasque
//
// Timer Column
//
- column = new Gtk.TreeViewColumn ();
- // Title for Timer Column
- column.Title = Catalog.GetString ("Timer");
- column.Sizing = Gtk.TreeViewColumnSizing.Fixed;
- column.FixedWidth = 20;
- column.Resizable = false;
-
- renderer = new Gtk.CellRendererPixbuf ();
- renderer.Xalign = 0.5f;
- column.PackStart (renderer, false);
- column.SetCellDataFunc (renderer,
- new Gtk.TreeCellDataFunc (TaskTimerCellDataFunc));
-
- AppendColumn (column);
+ timerCol = new TimerColumn (preferences, model);
+ timerCol.TimerExpired += (sender, e) => {
+ if (!e.Canceled)
+ e.Task.Complete ();
+ };
+
+ timerCol.Tick += (sender, e) => {
+ var status = string.Format (Catalog.GetString ("Completing Task In: {0}"), e.CountdownTick);
+ TaskWindow.ShowStatus (status, 2000);
+ };
+ AppendColumn (timerCol);
}
void CellRenderer_EditingStarted (object o, EditingStartedArgs args)
@@ -271,11 +263,7 @@ namespace Tasque
return;
taskBeingEdited = task;
-
- if (task.State != TaskState.Inactive)
- return;
-
- InactivateTimer.ToggleTimer (taskBeingEdited);
+ timerCol.PauseTimer (taskBeingEdited);
}
void SetCellRendererCallbacks (CellRendererText renderer, EditedHandler handler)
@@ -285,10 +273,9 @@ namespace Tasque
// Canceled: timer can continue.
renderer.EditingCanceled += (o, args) => {
if (taskBeingEdited != null) {
- if (taskBeingEdited.State == TaskState.Inactive) {
- taskBeingEdited.Inactivate ();
- InactivateTimer.ToggleTimer (taskBeingEdited);
- }
+ var timerState = timerCol.GetTimerState (taskBeingEdited);
+ if (timerState != null && (TimerColumn.TaskTimerState)timerState == TimerColumn.TaskTimerState.Paused)
+ timerCol.ResumeTimer (taskBeingEdited);
taskBeingEdited = null;
}
};
@@ -298,10 +285,9 @@ namespace Tasque
handler (o, args);
if (taskBeingEdited != null) {
- if (taskBeingEdited.State == TaskState.Inactive) {
- taskBeingEdited.Inactivate ();
- InactivateTimer.ToggleTimer (taskBeingEdited);
- }
+ var timerState = timerCol.GetTimerState (taskBeingEdited);
+ if (timerState != null && (TimerColumn.TaskTimerState)timerState == TimerColumn.TaskTimerState.Paused)
+ timerCol.ResumeTimer (taskBeingEdited);
taskBeingEdited = null;
}
};
@@ -352,8 +338,8 @@ namespace Tasque
if (task == null)
crt.Active = false;
else {
- crt.Active =
- task.State == TaskState.Active ? false : true;
+ var timerState = timerCol.GetTimerState (task);
+ crt.Active = !(task.State == TaskState.Active && timerState == null);
}
}
@@ -460,9 +446,12 @@ namespace Tasque
crt.Foreground = overdueTaskColor;
switch (task.State) {
- case TaskState.Inactive:
+ case TaskState.Active:
// Strikeout the text
- formatString = "<span strikethrough=\"true\">{0}</span>";
+ var timerState = timerCol.GetTimerState (task);
+ if (timerState != null && (TimerColumn.TaskTimerState)timerState
+ == TimerColumn.TaskTimerState.Running)
+ formatString = "<span strikethrough=\"true\">{0}</span>";
break;
case TaskState.Deleted:
case TaskState.Completed:
@@ -516,83 +505,6 @@ namespace Tasque
crp.Pixbuf = task.HasNotes ? notePixbuf : null;
}
- private void TaskTimerCellDataFunc (Gtk.TreeViewColumn treeColumn,
- Gtk.CellRenderer renderer, Gtk.TreeModel model,
- Gtk.TreeIter iter)
- {
- Gtk.CellRendererPixbuf crp = renderer as Gtk.CellRendererPixbuf;
- ITask task = model.GetValue (iter, 0) as ITask;
- if (task == null)
- return;
-
- if (task.State != TaskState.Inactive) {
- // The task is not in the inactive state so don't show any icon
- crp.Pixbuf = null;
- return;
- }
-
- int timerSeconds = preferences.GetInt (PreferencesKeys.InactivateTimeoutKey);
- // convert to milliseconds for more granularity
- long timeout = timerSeconds * 1000;
-
- //Logger.Debug ("TaskTimerCellDataFunc ()\n\tNow.Ticks: {0}\n\tCompletionDate.Ticks: {1}",
- // DateTime.Now.Ticks, task.CompletionDate.Ticks);
- long elapsedTicks = DateTime.Now.Ticks - task.CompletionDate.Ticks;
- //Logger.Debug ("\tElapsed Ticks: {0}", elapsedTicks);
- long elapsedMillis = elapsedTicks / 10000;
- //Logger.Debug ("\tElapsed Milliseconds: {0}", elapsedMillis);
-
- double percentComplete = (double)elapsedMillis / (double)timeout;
- //Logger.Debug ("\tPercent Complete: {0}", percentComplete);
-
- Gdk.Pixbuf pixbuf = GetIconForPercentage (percentComplete * 100);
- crp.Pixbuf = pixbuf;
- }
-
- protected static Gdk.Pixbuf GetIconForPercentage (double timeoutPercent)
- {
- int iconNum = GetIconNumForPercentage (timeoutPercent);
- if (iconNum == -1 || iconNum > 11)
- return null;
-
- return inactiveAnimPixbufs [iconNum];
- }
-
- protected static int GetIconNumForPercentage (double timeoutPercent)
- {
- //Logger.Debug ("GetIconNumForPercentage: {0}", timeoutPercent);
- int numOfIcons = 12;
- double percentIncrement = (double)100 / (double)numOfIcons;
- //Logger.Debug ("\tpercentIncrement: {0}", percentIncrement);
-
- if (timeoutPercent < percentIncrement)
- return 0;
- if (timeoutPercent < percentIncrement * 2)
- return 1;
- if (timeoutPercent < percentIncrement * 3)
- return 2;
- if (timeoutPercent < percentIncrement * 4)
- return 3;
- if (timeoutPercent < percentIncrement * 5)
- return 4;
- if (timeoutPercent < percentIncrement * 6)
- return 5;
- if (timeoutPercent < percentIncrement * 7)
- return 6;
- if (timeoutPercent < percentIncrement * 8)
- return 7;
- if (timeoutPercent < percentIncrement * 9)
- return 8;
- if (timeoutPercent < percentIncrement * 10)
- return 9;
- if (timeoutPercent < percentIncrement * 11)
- return 10;
- if (timeoutPercent < percentIncrement * 12)
- return 11;
-
- return -1;
- }
-
protected virtual bool FilterFunc (Gtk.TreeModel model,
Gtk.TreeIter iter)
{
@@ -629,8 +541,8 @@ namespace Tasque
if (task == null)
return;
- // remove any timer set up on this task
- InactivateTimer.CancelTimer(task);
+ // remove any timer set up on this task
+ timerCol.CancelTimer (task);
if (task.State == TaskState.Active) {
bool showCompletedTasks =
@@ -642,17 +554,8 @@ namespace Tasque
if (showCompletedTasks) {
task.Complete ();
ShowCompletedTaskStatus ();
- } else {
- task.Inactivate ();
-
- // Read the inactivate timeout from a preference
- int timeout =
- preferences.GetInt (PreferencesKeys.InactivateTimeoutKey);
- Logger.Debug ("Read timeout from prefs: {0}", timeout);
- InactivateTimer timer =
- new InactivateTimer (this, iter, task, (uint) timeout);
- timer.StartTimer ();
- }
+ } else
+ timerCol.StartTimer (task);
} else {
status = Catalog.GetString ("Action Canceled");
TaskWindow.ShowStatus (status);
@@ -806,157 +709,5 @@ namespace Tasque
NumberOfTasksChanged (this, EventArgs.Empty);
}
#endregion // EventHandlers
-
- #region Private Classes
- /// <summary>
- /// Does the work of walking a task through the Inactive -> Complete
- /// states
- /// </summary>
- class InactivateTimer
- {
- /// <summary>
- /// Keep track of all the timers so that the pulseTimeoutId can
- /// be removed at the proper time.
- /// </summary>
- private static Dictionary<uint, InactivateTimer> timers;
-
- static InactivateTimer ()
- {
- timers = new Dictionary<uint,InactivateTimer> ();
- }
-
- private TaskTreeView tree;
- private ITask task;
- private uint delay;
- private uint secondsLeft;
- protected uint pulseTimeoutId;
- private uint secondTimerId;
- private Gtk.TreeIter iter;
- private Gtk.TreePath path;
-
- public InactivateTimer (TaskTreeView treeView,
- Gtk.TreeIter taskIter,
- ITask taskToComplete,
- uint delayInSeconds)
- {
- tree = treeView;
- iter = taskIter;
- path = treeView.Model.GetPath (iter);
- task = taskToComplete;
- secondsLeft = delayInSeconds;
- delay = delayInSeconds * 1000; // Convert to milliseconds
- pulseTimeoutId = 0;
- }
-
- public bool Paused {
- get; set;
- }
-
- public void StartTimer ()
- {
- pulseTimeoutId = GLib.Timeout.Add (500, PulseAnimation);
- StartSecondCountdown ();
- task.TimerID = GLib.Timeout.Add (delay, CompleteTask);
- timers [task.TimerID] = this;
- }
-
- public static void ToggleTimer (ITask task)
- {
- InactivateTimer timer = null;
- if (timers.TryGetValue (task.TimerID, out timer))
- timer.Paused = !timer.Paused;
- }
-
- public static void CancelTimer(ITask task)
- {
- Logger.Debug ("Timeout Canceled for task: " + task.Name);
- InactivateTimer timer = null;
- uint timerId = task.TimerID;
- if(timerId != 0) {
- if (timers.ContainsKey (timerId)) {
- timer = timers [timerId];
- timers.Remove (timerId);
- }
- GLib.Source.Remove(timerId);
- GLib.Source.Remove (timer.pulseTimeoutId);
- timer.pulseTimeoutId = 0;
- task.TimerID = 0;
- }
-
- if (timer != null) {
- GLib.Source.Remove (timer.pulseTimeoutId);
- timer.pulseTimeoutId = 0;
- GLib.Source.Remove (timer.secondTimerId);
- timer.secondTimerId = 0;
- timer.Paused = false;
- }
- }
-
- private bool CompleteTask ()
- {
- if (!Paused) {
- GLib.Source.Remove (pulseTimeoutId);
- if (timers.ContainsKey (task.TimerID))
- timers.Remove (task.TimerID);
-
- if(task.State != TaskState.Inactive)
- return false;
-
- task.Complete ();
- ShowCompletedTaskStatus ();
- tree.Refilter ();
- return false; // Don't automatically call this handler again
- }
-
- return true;
- }
-
- private bool PulseAnimation ()
- {
- if (tree.Model == null) {
- // Widget has been closed, no need to call this again
- return false;
- } else {
- if (!Paused) {
- // Emit this signal to cause the TreeView to update the row
- // where the task is located. This will allow the
- // CellRendererPixbuf to update the icon.
- tree.Model.EmitRowChanged (path, iter);
-
- // Return true so that this method will be called after an
- // additional timeout duration has elapsed.
- return true;
- }
- }
-
- return true;
- }
-
- private void StartSecondCountdown ()
- {
- SecondCountdown();
- secondTimerId = GLib.Timeout.Add (1000, SecondCountdown);
- }
-
- private bool SecondCountdown ()
- {
- if (tree.Model == null) {
- // Widget has been closed, no need to call this again
- return false;
- }
- if (!Paused) {
- if (secondsLeft > 0 && task.State == TaskState.Inactive) {
- status = String.Format (Catalog.GetString ("Completing Task In: {0}"), secondsLeft--);
- TaskWindow.ShowStatus (status);
- return true;
- } else {
- return false;
- }
- }
- return true;
- }
-
- }
- #endregion // Private Classes
}
}
diff --git a/src/Gtk.Tasque/TaskWindow.cs b/src/Gtk.Tasque/TaskWindow.cs
index 9576fb7..5bbd8c7 100644
--- a/src/Gtk.Tasque/TaskWindow.cs
+++ b/src/Gtk.Tasque/TaskWindow.cs
@@ -35,10 +35,10 @@ using System.Linq;
using Gdk;
using Gtk;
using Mono.Unix;
-
+using Tasque;
using Tasque.Backends;
-namespace Tasque
+namespace Gtk.Tasque
{
public class TaskWindow : Gtk.Window
{
@@ -670,7 +670,7 @@ namespace Tasque
int count = 0;
var model = application.Backend.Tasks;
count = model.Count (t => t != null &&
- (t.State == TaskState.Active || t.State == TaskState.Inactive) &&
+ t.State == TaskState.Active &&
category.ContainsTask (t));
return count;
}
diff --git a/src/Gtk.Tasque/TimerColumn.cs b/src/Gtk.Tasque/TimerColumn.cs
new file mode 100644
index 0000000..d8359e0
--- /dev/null
+++ b/src/Gtk.Tasque/TimerColumn.cs
@@ -0,0 +1,317 @@
+//
+// TimerColumn.cs
+//
+// Author:
+// Antonius Riha <antoniusriha gmail com>
+//
+// Copyright (c) 2013 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.Concurrent;
+using System.Timers;
+using Mono.Unix;
+using Tasque;
+using Gdk;
+
+namespace Gtk.Tasque
+{
+ public class TimerColumn : TreeViewColumn
+ {
+ public TimerColumn (IPreferences preferences, TreeModel model)
+ {
+ if (model == null)
+ throw new ArgumentNullException ("model");
+ this.model = model;
+ if (preferences == null)
+ throw new ArgumentNullException ("preferences");
+ this.preferences = preferences;
+
+ timeoutTargets = new ConcurrentDictionary<ITask, TaskTimer> ();
+
+ Title = Catalog.GetString ("Timer");
+ Sizing = TreeViewColumnSizing.Fixed;
+ FixedWidth = 20;
+ Resizable = false;
+
+ var renderer = new CellRendererPixbuf { Xalign = 0.5f };
+ PackStart (renderer, false);
+ SetCellDataFunc (renderer, TaskTimerCellDataFunc);
+ }
+
+ public void StartTimer (ITask task)
+ {
+ if (task == null)
+ throw new ArgumentNullException ("task");
+
+ var timeout = preferences.GetInt (PreferencesKeys.InactivateTimeoutKey);
+ TreeIter treeIter;
+ var iterFound = false;
+ model.Foreach ((treeModel, treePath, iter) => {
+ if (treeModel.GetValue (iter, 0) == task) {
+ treeIter = iter;
+ iterFound = true;
+ return true;
+ }
+ return false;
+ });
+
+ var timer = new TaskTimer (timeout, treeIter, model);
+ // if no iter found for task or this task exists in the timer dictinary, return
+ // silently (this is a concurrency sensitive area, hence we shouldn't be to
+ // strict if it is called multiple times)
+ if (!iterFound || !timeoutTargets.TryAdd (task, timer))
+ return;
+
+ timer.TimerStopped += (sender, e) => {
+ TaskTimer tmr;
+ timeoutTargets.TryRemove (e.Task, out tmr);
+ if (TimerExpired != null)
+ TimerExpired (this, e);
+ };
+
+ timer.Tick += (sender, e) => {
+ if (Tick != null)
+ Tick (this, e);
+ };
+
+ timer.Start ();
+ }
+
+ public void PauseTimer (ITask task)
+ {
+ if (task == null)
+ return;
+ TaskTimer timer;
+ if (timeoutTargets.TryGetValue (task, out timer))
+ timer.Pause ();
+ }
+
+ public void ResumeTimer (ITask task)
+ {
+ if (task == null)
+ return;
+ TaskTimer timer;
+ if (timeoutTargets.TryGetValue (task, out timer))
+ timer.Resume ();
+ }
+
+ public TaskTimerState? GetTimerState (ITask task)
+ {
+ if (task == null)
+ throw new ArgumentNullException ("task");
+ TaskTimer timer;
+ if (!timeoutTargets.TryGetValue (task, out timer))
+ return null;
+ return timer.State;
+ }
+
+ public void CancelTimer (ITask task)
+ {
+ if (task == null)
+ return;
+ TaskTimer timer;
+ if (timeoutTargets.TryRemove (task, out timer))
+ timer.Cancel ();
+ }
+
+ public event EventHandler<TickEventArgs> Tick;
+
+ public event EventHandler<TimerExpiredEventArgs> TimerExpired;
+
+ void TaskTimerCellDataFunc (TreeViewColumn treeColumn, CellRenderer cell,
+ TreeModel treeModel, TreeIter iter)
+ {
+ var task = treeModel.GetValue (iter, 0) as ITask;
+ TaskTimer timer;
+ var crp = cell as CellRendererPixbuf;
+ if (task == null || !timeoutTargets.TryGetValue (task, out timer)) {
+ crp.Pixbuf = null;
+ return;
+ }
+
+ crp.Pixbuf = timer.CurrentAnimPixbuf;
+ }
+
+ ConcurrentDictionary<ITask, TaskTimer> timeoutTargets;
+ IPreferences preferences;
+ TreeModel model;
+
+ public class TimerExpiredEventArgs : EventArgs
+ {
+ public TimerExpiredEventArgs (ITask task, bool canceled)
+ {
+ if (task == null)
+ throw new ArgumentNullException ("task");
+ Task = task;
+ Canceled = canceled;
+ }
+
+ public bool Canceled { get; private set; }
+
+ public ITask Task { get; private set; }
+ }
+
+ public class TickEventArgs : EventArgs
+ {
+ public TickEventArgs (int tick, ITask task)
+ {
+ if (task == null)
+ throw new ArgumentNullException ("task");
+ Task = task;
+ CountdownTick = tick;
+ }
+
+ public int CountdownTick { get; private set; }
+
+ public ITask Task { get; private set; }
+ }
+
+ public enum TaskTimerState
+ {
+ NotStarted,
+ Running,
+ Paused,
+ Stopped
+ }
+
+ class TaskTimer
+ {
+ static TaskTimer ()
+ {
+ inactiveAnimPixbufs = new Pixbuf [12];
+ for (int i = 0; i < 12; i++) {
+ var iconName = string.Format ("tasque-completing-{0}", i);
+ inactiveAnimPixbufs [i] = Utilities.GetIcon (iconName, 16);
+ }
+ }
+
+ static Pixbuf [] inactiveAnimPixbufs;
+
+ public TaskTimer (int timeout, TreeIter iter, TreeModel model)
+ {
+ if (model == null)
+ throw new ArgumentNullException ("model");
+ if (timeout < 0)
+ timeout = 5;
+
+ CurrentAnimPixbuf = inactiveAnimPixbufs [0];
+
+ long lngTimeout = timeout * 1000;
+ var interval = lngTimeout / (double)inactiveAnimPixbufs.Length;
+
+ this.model = model;
+ this.iter = iter;
+
+ timer = new Timer (interval);
+ timer.Elapsed += delegate {
+ try {
+ CurrentAnimPixbuf = inactiveAnimPixbufs [++i];
+ NotifyChange ();
+ } catch (IndexOutOfRangeException) {
+ StopTimer (false);
+ }
+ };
+
+ countdown = timeout;
+ sTimer = new Timer (1000);
+ sTimer.Elapsed += delegate {
+ if (countdown == 0) {
+ sTimer.Dispose ();
+ return;
+ }
+
+ var task = model.GetValue (iter, 0) as ITask;
+ if (task == null)
+ return;
+
+ if (Tick != null)
+ Tick (this, new TickEventArgs (--countdown, task));
+ };
+ }
+
+ public Pixbuf CurrentAnimPixbuf { get; private set; }
+
+ public TaskTimerState State { get; private set; }
+
+ public void Start ()
+ {
+ timer.Start ();
+ sTimer.Start ();
+ State = TaskTimerState.Running;
+ NotifyChange ();
+ }
+
+ public void Pause ()
+ {
+ timer.Stop ();
+ sTimer.Stop ();
+ State = TaskTimerState.Paused;
+ NotifyChange ();
+ }
+
+ public void Resume ()
+ {
+ timer.Start ();
+ sTimer.Start ();
+ State = TaskTimerState.Running;
+ NotifyChange ();
+ }
+
+ public void Cancel ()
+ {
+ StopTimer (true);
+ }
+
+ public event EventHandler<TickEventArgs> Tick;
+
+ public event EventHandler<TimerExpiredEventArgs> TimerStopped;
+
+ void NotifyChange ()
+ {
+ var path = model.GetPath (iter);
+ model.EmitRowChanged (path, iter);
+ }
+
+ void StopTimer (bool canceled)
+ {
+ timer.Dispose ();
+ sTimer.Dispose ();
+ State = TaskTimerState.Stopped;
+ CurrentAnimPixbuf = null;
+
+ var task = model.GetValue (iter, 0) as ITask;
+ if (task == null)
+ return;
+
+ NotifyChange ();
+
+ if (TimerStopped != null)
+ TimerStopped (this, new TimerExpiredEventArgs (task, canceled));
+ }
+
+ int i;
+ int countdown;
+ TreeModel model;
+ TreeIter iter;
+ Timer timer;
+ Timer sTimer;
+ }
+ }
+}
diff --git a/src/Gtk.Tasque/TimerTaskField.cs b/src/Gtk.Tasque/TimerTaskField.cs
new file mode 100644
index 0000000..62066d4
--- /dev/null
+++ b/src/Gtk.Tasque/TimerTaskField.cs
@@ -0,0 +1,44 @@
+//
+// TimerTaskField.cs
+//
+// Author:
+// Antonius Riha <antoniusriha gmail com>
+//
+// Copyright (c) 2013 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 Tasque;
+
+namespace Gtk.Tasque
+{
+ public class TimerTaskField : ITaskField
+ {
+ public TimerTaskField ()
+ {
+ }
+
+ public string HeaderText { get; set; }
+
+ public void Initialize (ITask task)
+ {
+ throw new NotImplementedException ();
+ }
+ }
+}
diff --git a/src/libtasque/AbstractTask.cs b/src/libtasque/AbstractTask.cs
index 74d2b09..fca91d4 100644
--- a/src/libtasque/AbstractTask.cs
+++ b/src/libtasque/AbstractTask.cs
@@ -86,7 +86,6 @@ namespace Tasque
#region Methods
public abstract void Activate ();
- public abstract void Inactivate ();
public abstract void Complete ();
public abstract void Delete ();
public abstract INote CreateNote(string text);
diff --git a/src/libtasque/ITask.cs b/src/libtasque/ITask.cs
index f5a4446..fd2e593 100644
--- a/src/libtasque/ITask.cs
+++ b/src/libtasque/ITask.cs
@@ -122,16 +122,11 @@ namespace Tasque
#region Methods
/// <summary>
- /// Activate (Reopen) a task that's Inactivated or Completed.
+ /// Activate (Reopen) a task that's Completed.
/// </summary>
void Activate ();
/// <summary>
- /// Inactivate a task (this is the "limbo" mode).
- /// </summary>
- void Inactivate ();
-
- /// <summary>
/// Mark a task as completed.
/// </summary>
void Complete ();
diff --git a/src/libtasque/TaskGroupModel.cs b/src/libtasque/TaskGroupModel.cs
index 51f0ed7..770ce7e 100644
--- a/src/libtasque/TaskGroupModel.cs
+++ b/src/libtasque/TaskGroupModel.cs
@@ -335,11 +335,6 @@ namespace Tasque
throw new NotSupportedException ();
}
- void ITask.Inactivate ()
- {
- throw new NotSupportedException ();
- }
-
void ITask.Complete ()
{
throw new NotSupportedException ();
diff --git a/src/libtasque/TaskState.cs b/src/libtasque/TaskState.cs
index 41ffa11..c7cdb11 100644
--- a/src/libtasque/TaskState.cs
+++ b/src/libtasque/TaskState.cs
@@ -13,13 +13,6 @@ namespace Tasque
Active,
/// <summary>
- /// A task that's in limbo...the user has clicked that it should be
- /// completed, but we're delaying so the user can get a visual of what's
- /// gonna happen. This feature ROCKS!
- /// </summary>
- Inactive,
-
- /// <summary>
/// A completed task.
/// </summary>
Completed,
diff --git a/src/tasque/Program.cs b/src/tasque/Program.cs
index 4041152..8b98e39 100644
--- a/src/tasque/Program.cs
+++ b/src/tasque/Program.cs
@@ -27,6 +27,7 @@ using System;
using System.Runtime.InteropServices;
using System.Text;
using Mono.Unix.Native;
+using Gtk.Tasque;
namespace Tasque
{
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]