[tasque] Fix crash when "task done" animation is running and task values are manually changed (bgo #591090)
- From: Mario Carrion <mcarrion src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [tasque] Fix crash when "task done" animation is running and task values are manually changed (bgo #591090)
- Date: Mon, 19 Apr 2010 21:20:38 +0000 (UTC)
commit 26c4fed8bde471b144100411180da343a38a9f90
Author: Mario Carrion <mario carrion mx>
Date: Mon Apr 19 17:20:10 2010 -0400
Fix crash when "task done" animation is running and task values are manually changed (bgo #591090)
src/TaskTreeView.cs | 129 +++++++++++++++++++++++++++++++++++++++-----------
1 files changed, 100 insertions(+), 29 deletions(-)
---
diff --git a/src/TaskTreeView.cs b/src/TaskTreeView.cs
index 8511ff7..b9f2569 100644
--- a/src/TaskTreeView.cs
+++ b/src/TaskTreeView.cs
@@ -19,7 +19,8 @@ namespace Tasque
private static Gdk.Pixbuf[] inactiveAnimPixbufs;
private Gtk.TreeModelFilter modelFilter;
- private ICategory filterCategory;
+ private ICategory filterCategory;
+ private ITask taskBeingEdited = null;
private static string status;
@@ -109,7 +110,7 @@ namespace Tasque
renderer = new Gtk.CellRendererCombo ();
(renderer as Gtk.CellRendererCombo).Editable = true;
(renderer as Gtk.CellRendererCombo).HasEntry = false;
- (renderer as Gtk.CellRendererCombo).Edited += OnTaskPriorityEdited;
+ SetCellRendererCallbacks ((CellRendererCombo) renderer, OnTaskPriorityEdited);
Gtk.ListStore priorityStore = new Gtk.ListStore (typeof (string));
priorityStore.AppendValues (Catalog.GetString ("1")); // High
priorityStore.AppendValues (Catalog.GetString ("2")); // Medium
@@ -145,7 +146,7 @@ namespace Tasque
column.SetCellDataFunc (renderer,
new Gtk.TreeCellDataFunc (TaskNameTextCellDataFunc));
((Gtk.CellRendererText)renderer).Editable = true;
- ((Gtk.CellRendererText)renderer).Edited += OnTaskNameEdited;
+ SetCellRendererCallbacks ((CellRendererText) renderer, OnTaskNameEdited);
AppendColumn (column);
@@ -180,7 +181,7 @@ namespace Tasque
renderer = new Gtk.CellRendererCombo ();
(renderer as Gtk.CellRendererCombo).Editable = true;
(renderer as Gtk.CellRendererCombo).HasEntry = false;
- (renderer as Gtk.CellRendererCombo).Edited += OnDateEdited;
+ SetCellRendererCallbacks ((CellRendererCombo) renderer, OnDateEdited);
Gtk.ListStore dueDateStore = new Gtk.ListStore (typeof (string));
DateTime today = DateTime.Now;
dueDateStore.AppendValues (
@@ -246,7 +247,47 @@ namespace Tasque
AppendColumn (column);
}
+
+ void CellRenderer_EditingStarted (object o, EditingStartedArgs args)
+ {
+ Gtk.TreeIter iter;
+ Gtk.TreePath path = new Gtk.TreePath (args.Path);
+ if (!Model.GetIter (out iter, path))
+ return;
+
+ ITask task = Model.GetValue (iter, 0) as ITask;
+ if (task == null)
+ return;
+
+ taskBeingEdited = task;
+ InactivateTimer.ToggleTimer (taskBeingEdited);
+ }
+ void SetCellRendererCallbacks (CellRendererText renderer, EditedHandler handler)
+ {
+ // The user is going to "edit" or "cancel", timer can't continue.
+ renderer.EditingStarted += CellRenderer_EditingStarted;
+ // Canceled: timer can continue.
+ renderer.EditingCanceled += (o, args) => {
+ if (taskBeingEdited != null) {
+ taskBeingEdited.Inactivate ();
+ InactivateTimer.ToggleTimer (taskBeingEdited);
+ taskBeingEdited = null;
+ }
+ };
+ // Edited: after calling the delegate the timer can continue.
+ renderer.Edited += (o, args) => {
+ if (handler != null)
+ handler (o, args);
+
+ if (taskBeingEdited != null) {
+ taskBeingEdited.Inactivate ();
+ InactivateTimer.ToggleTimer (taskBeingEdited);
+ taskBeingEdited = null;
+ }
+ };
+ }
+
#region Public Methods
public void Refilter ()
{
@@ -355,6 +396,9 @@ namespace Tasque
// TODO: Add bold (for high), light (for None), and also colors to priority?
Gtk.CellRendererCombo crc = cell as Gtk.CellRendererCombo;
ITask task = Model.GetValue (iter, 0) as ITask;
+ if (task == null)
+ return;
+
switch (task.Priority) {
case TaskPriority.Low:
crc.Text = Catalog.GetString ("3");
@@ -783,6 +827,10 @@ namespace Tasque
pulseTimeoutId = 0;
}
+ public bool Paused {
+ get; set;
+ }
+
public void StartTimer ()
{
pulseTimeoutId = GLib.Timeout.Add (500, PulseAnimation);
@@ -790,7 +838,14 @@ namespace Tasque
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);
@@ -802,28 +857,37 @@ namespace Tasque
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 ()
{
- GLib.Source.Remove (pulseTimeoutId);
- if (timers.ContainsKey (task.TimerID))
- timers.Remove (task.TimerID);
-
- if(task.State != TaskState.Inactive)
- return false;
+ if (!Paused) {
+ GLib.Source.Remove (pulseTimeoutId);
+ if (timers.ContainsKey (task.TimerID))
+ timers.Remove (task.TimerID);
- task.Complete ();
- ShowCompletedTaskStatus ();
- tree.Refilter ();
- return false; // Don't automatically call this handler again
+ 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 ()
@@ -832,15 +896,19 @@ namespace Tasque
// Widget has been closed, no need to call this again
return false;
} else {
- // 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;
+ 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 ()
@@ -855,13 +923,16 @@ namespace Tasque
// Widget has been closed, no need to call this again
return false;
}
- 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;
+ 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;
}
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]