[tasque] Initial implementation of tooltip for the tray icon (bug #532915)



commit 14007ac46cba93aff1140dd88a3e3a614f1b3468
Author: Peter Johanson <peter peterjohanson com>
Date:   Fri Sep 18 15:57:57 2009 -0700

    Initial implementation of tooltip for the tray icon (bug #532915)
    
    So..... Here's my initial stab at implementing this.
    
    When digging into this, I noticed a few things that I had to tweak:
    
    1) Application.Backend had lots of logic that just manipulated the Application
    *instance*, so I moved this logic (with my additions) into an
    Application.SetBackend (IBackend backend) instance method. Cool and the gang?
    
    2) Most of the logic for filtering out what items where in "Today", "Tomorrow",
    etc was in TaskGroup, which was a *GUI* thing, not a data/model thing. In order
    to reuse the code, I created new classes TaskGroupModel, and
    CompleteTaskGroupModel, to encapsulate that logic, and make TaskGroup and
    CompleteTaskGroup make use of those models. That ok? Other suggestions?
    
    3) Ideally, the "today_model", "tomorrow_model", private fields in
    Tasque.Application could also be shared with the TaskGroup instances in the
    TaskMainWindow. I've not done this yet in this patch, so there's some extra
    memory/CPU used here that could be avoided. Worth addressing in this patch?
    Suggestions on a nice approach to doing that?
    
    Any other feedback welcome as well, of course.

 src/Application.cs             |  173 +++++++++++++++++++++++++++++++---------
 src/CompletedTaskGroup.cs      |   50 +----------
 src/CompletedTaskGroupModel.cs |   57 +++++++++++++
 src/Makefile.am                |    3 +
 src/TaskGroup.cs               |  107 +++++--------------------
 src/TaskGroupModel.cs          |  109 +++++++++++++++++++++++++
 src/TaskGroupModelFactory.cs   |   43 ++++++++++
 tasque.mdp                     |    8 +-
 8 files changed, 379 insertions(+), 171 deletions(-)
---
diff --git a/src/Application.cs b/src/Application.cs
index 458bc9e..5f151a0 100644
--- a/src/Application.cs
+++ b/src/Application.cs
@@ -61,6 +61,7 @@ namespace Tasque
 		private Preferences preferences;
 		private EventBox eb;
 		private IBackend backend;
+		private TaskGroupModel overdue_tasks, today_tasks, tomorrow_tasks;
 		private PreferencesDialog preferencesDialog;
 		private bool quietStart = false;
 		
@@ -93,43 +94,7 @@ namespace Tasque
 		public static IBackend Backend
 		{ 
 			get { return Application.Instance.backend; }
-			set {
-				bool changingBackend = false;
-				Application tasque = Application.Instance;
-				if (tasque.backend != null) {
-					changingBackend = true;
-					// Cleanup the old backend
-					try {
-						Logger.Debug ("Cleaning up backend: {0}",
-									  tasque.backend.Name);
-						tasque.backend.Cleanup ();
-					} catch (Exception e) {
-						Logger.Warn ("Exception cleaning up '{0}': {1}",
-									 tasque.backend.Name,
-									 e);
-					}
-				}
-					
-				// Initialize the new backend
-				tasque.backend = value;
-				if (tasque.backend == null) {
-					return;
-				}
-					
-				Logger.Info ("Using backend: {0} ({1})",
-							 tasque.backend.Name,
-							 tasque.backend.GetType ().ToString ());
-				tasque.backend.Initialize();
-				
-				if (!changingBackend) {
-					TaskWindow.Reinitialize (!Instance.quietStart);
-				} else {
-					TaskWindow.Reinitialize (true);
-				}
-				
-				Logger.Debug("Configuration status: {0}",
-							 tasque.backend.Configured.ToString());
-			}
+			set { Application.Instance.SetBackend (value); }
 		}
 		
 		public static List<IBackend> AvailableBackends
@@ -370,6 +335,49 @@ namespace Tasque
 			return backends;
 		}
 
+		private void SetBackend (IBackend value)
+		{
+			bool changingBackend = false;
+			if (this.backend != null) {
+				UnhookFromTooltipTaskGroupModels ();
+				changingBackend = true;
+				// Cleanup the old backend
+				try {
+					Logger.Debug ("Cleaning up backend: {0}",
+					              this.backend.Name);
+					this.backend.Cleanup ();
+				} catch (Exception e) {
+					Logger.Warn ("Exception cleaning up '{0}': {1}",
+					             this.backend.Name,
+					             e);
+				}
+			}
+				
+			// Initialize the new backend
+			this.backend = value;
+			if (this.backend == null) {
+				RefreshTrayIconTooltip ();
+				return;
+			}
+				
+			Logger.Info ("Using backend: {0} ({1})",
+			             this.backend.Name,
+			             this.backend.GetType ().ToString ());
+			this.backend.Initialize();
+			
+			if (!changingBackend) {
+				TaskWindow.Reinitialize (!this.quietStart);
+			} else {
+				TaskWindow.Reinitialize (true);
+			}
+
+			RebuildTooltipTaskGroupModels ();
+			RefreshTrayIconTooltip ();
+			
+			Logger.Debug("Configuration status: {0}",
+			             this.backend.Configured.ToString());
+		}
+
 		private bool InitializeIdle()
 		{
 			if (customBackend != null) {
@@ -427,6 +435,10 @@ namespace Tasque
 				// Reinitialize window according to new date
 				if (TaskWindow.IsOpen)
 					TaskWindow.Reinitialize (true);
+				
+				UnhookFromTooltipTaskGroupModels ();
+				RebuildTooltipTaskGroupModels ();
+				RefreshTrayIconTooltip ();
 			}
 			
 			return true;
@@ -444,7 +456,91 @@ namespace Tasque
 			// showing the trayicon
 			trayIcon.Visible = true;
 
-			trayIcon.Tooltip = "Tasque Rocks";
+			RefreshTrayIconTooltip ();
+		}
+
+		private void UnhookFromTooltipTaskGroupModels ()
+		{
+			foreach (TaskGroupModel model in new TaskGroupModel[] { overdue_tasks, today_tasks, tomorrow_tasks })
+			{
+				if (model == null) {
+					continue;
+				}
+				
+				model.RowInserted -= OnTooltipModelChanged;
+				model.RowChanged -= OnTooltipModelChanged;
+				model.RowDeleted -= OnTooltipModelChanged;
+			}
+		}
+
+		private void OnTooltipModelChanged (object o, EventArgs args)
+		{
+			RefreshTrayIconTooltip ();
+		}
+
+		private void RebuildTooltipTaskGroupModels ()
+		{
+			if (backend == null || backend.Tasks == null) {
+				overdue_tasks = null;
+				today_tasks = null;
+				tomorrow_tasks = null;
+				
+				return;
+			}
+
+			overdue_tasks = TaskGroupModelFactory.CreateOverdueModel (backend.Tasks);
+			today_tasks = TaskGroupModelFactory.CreateTodayModel (backend.Tasks);
+			tomorrow_tasks = TaskGroupModelFactory.CreateTomorrowModel (backend.Tasks);
+
+			foreach (TaskGroupModel model in new TaskGroupModel[] { overdue_tasks, today_tasks, tomorrow_tasks })
+			{
+				if (model == null) {
+					continue;
+				}
+				
+				model.RowInserted += OnTooltipModelChanged;
+				model.RowChanged += OnTooltipModelChanged;
+				model.RowDeleted += OnTooltipModelChanged;
+			}
+		}
+		
+		private void RefreshTrayIconTooltip ()
+		{
+			if (trayIcon == null) {
+				return;
+			}
+
+			StringBuilder sb = new StringBuilder ();
+			if (overdue_tasks != null) {
+				int count =  overdue_tasks.IterNChildren ();
+
+				if (count > 0) {
+					sb.Append (String.Format (Catalog.GetPluralString ("{0} task is Overdue\n", "{0} tasks are Overdue\n", count), count));
+				}
+			}
+			
+			if (today_tasks != null) {
+				int count =  today_tasks.IterNChildren ();
+
+				if (count > 0) {
+					sb.Append (String.Format (Catalog.GetPluralString ("{0} task for Today\n", "{0} tasks for Today\n", count), count));
+				}
+			}
+
+			if (tomorrow_tasks != null) {
+				int count =  tomorrow_tasks.IterNChildren ();
+
+				if (count > 0) {
+					sb.Append (String.Format (Catalog.GetPluralString ("{0} task for Tomorrow\n", "{0} tasks for Tomorrow\n", count), count));
+				}
+			}
+
+			if (sb.Length == 0) {
+				trayIcon.Tooltip = "Tasque Rocks";
+				return;
+			}
+
+			trayIcon.Tooltip = sb.ToString ().TrimEnd ('\n');
 		}
 
 
@@ -524,6 +620,7 @@ namespace Tasque
 		{
 			Logger.Info ("OnQuit called - terminating application");
 			if (backend != null) {
+				UnhookFromTooltipTaskGroupModels ();
 				backend.Cleanup();
 			}
 			TaskWindow.SavePosition();
diff --git a/src/CompletedTaskGroup.cs b/src/CompletedTaskGroup.cs
index 6bc7c71..9b0b0df 100644
--- a/src/CompletedTaskGroup.cs
+++ b/src/CompletedTaskGroup.cs
@@ -74,52 +74,12 @@ namespace Tasque
 			
 			this.ExtraWidget = rangeSlider;
 		}
-		
-		/// <summary>
-		/// Override the default filter mechanism so that we show only
-		/// completed tasks in this group.
-		/// </summary>
-		/// <param name="model">
-		/// A <see cref="TreeModel"/>
-		/// </param>
-		/// <param name="iter">
-		/// A <see cref="TreeIter"/>
-		/// </param>
-		/// <returns>
-		/// A <see cref="System.Boolean"/>
-		/// </returns>
-		protected override bool FilterTasks (TreeModel model, TreeIter iter)
+
+		protected override TaskGroupModel CreateModel (DateTime rangeStart,
+		                                               DateTime rangeEnd,
+		                                               TreeModel tasks)
 		{
-			// Don't show any task here if showCompletedTasks is false
-			if (!showCompletedTasks)
-				return false;
-			
-			ITask task = model.GetValue (iter, 0) as ITask;
-			if (task == null || task.State != TaskState.Completed)
-				return false;
-			
-			if (selectedCategory != null
-					&& !selectedCategory.ContainsTask (task))
-				return false;
-			
-			// Make sure that the task fits into the specified range depending
-			// on what the user has set the range slider to be.
-			if (task.CompletionDate < this.TimeRangeStart)
-				return false;
-			
-			if (task.CompletionDate == DateTime.MinValue)
-				return true; // Just in case
-			
-			// Don't show tasks in the completed group that were completed
-			// today.  Tasks completed today should still appear under their
-			// original group until tomorrow.
-			DateTime today = DateTime.Now;
-			
-			if (today.Year == task.CompletionDate.Year
-					&& today.DayOfYear == task.CompletionDate.DayOfYear)
-				return false;
-			
-			return true;
+			return new CompletedTaskGroupModel (rangeStart, rangeEnd, tasks);
 		}
 		
 		protected void OnSelectedCategorySettingChanged (
diff --git a/src/CompletedTaskGroupModel.cs b/src/CompletedTaskGroupModel.cs
new file mode 100644
index 0000000..0db7cbe
--- /dev/null
+++ b/src/CompletedTaskGroupModel.cs
@@ -0,0 +1,57 @@
+
+using System;
+using Gtk;
+
+namespace Tasque
+{
+	public class CompletedTaskGroupModel : TaskGroupModel
+	{
+		public CompletedTaskGroupModel (DateTime rangeStart, DateTime rangeEnd, TreeModel tasks)
+			: base (rangeStart, rangeEnd, tasks)
+		{
+		}
+
+		/// <summary>
+		/// Override the default filter mechanism so that we show only
+		/// completed tasks in this group.
+		/// </summary>
+		/// <param name="model">
+		/// A <see cref="TreeModel"/>
+		/// </param>
+		/// <param name="iter">
+		/// A <see cref="TreeIter"/>
+		/// </param>
+		/// <returns>
+		/// A <see cref="System.Boolean"/>
+		/// </returns>
+		protected override bool FilterTasks (TreeModel model, TreeIter iter)
+		{
+			// Don't show any task here if showCompletedTasks is false
+			if (!showCompletedTasks)
+				return false;
+			
+			ITask task = model.GetValue (iter, 0) as ITask;
+			if (task == null || task.State != TaskState.Completed)
+				return false;
+			
+			// Make sure that the task fits into the specified range depending
+			// on what the user has set the range slider to be.
+			if (task.CompletionDate < this.timeRangeStart)
+				return false;
+			
+			if (task.CompletionDate == DateTime.MinValue)
+				return true; // Just in case
+			
+			// Don't show tasks in the completed group that were completed
+			// today.  Tasks completed today should still appear under their
+			// original group until tomorrow.
+			DateTime today = DateTime.Now;
+			
+			if (today.Year == task.CompletionDate.Year
+					&& today.DayOfYear == task.CompletionDate.DayOfYear)
+				return false;
+			
+			return true;
+		}
+	}
+}
diff --git a/src/Makefile.am b/src/Makefile.am
index 0489b3f..162a825 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -80,6 +80,9 @@ CSFILES = \
 	$(srcdir)/RemoteControl.cs \
 	$(srcdir)/RemoteControlProxy.cs \
 	$(srcdir)/TaskCalendar.cs \
+	$(srcdir)/TaskGroupModel.cs \
+	$(srcdir)/CompletedTaskGroupModel.cs \
+	$(srcdir)/TaskGroupModelFactory.cs \
 	$(srcdir)/TaskGroup.cs \
 	$(srcdir)/TaskPriority.cs \
 	$(srcdir)/TaskState.cs \
diff --git a/src/TaskGroup.cs b/src/TaskGroup.cs
index 9351189..7b0ac6e 100644
--- a/src/TaskGroup.cs
+++ b/src/TaskGroup.cs
@@ -14,41 +14,32 @@ namespace Tasque
 	/// </summary>
 	public class TaskGroup : Gtk.VBox
 	{
-		DateTime timeRangeStart;
-		DateTime timeRangeEnd;
-		
 		Gtk.Label header;
 		TaskTreeView treeView;
-		Gtk.TreeModelFilter filteredTasks;
+		TaskGroupModel filteredTasks;
 		Gtk.HBox extraWidgetHBox;
 		Gtk.Widget extraWidget;
 		
 		bool hideWhenEmpty;
 		
-		protected bool showCompletedTasks;
-		
 		#region Constructor
 		public TaskGroup (string groupName, DateTime rangeStart,
 						  DateTime rangeEnd, Gtk.TreeModel tasks)
 		{
-			this.timeRangeStart = rangeStart;
-			this.timeRangeEnd = rangeEnd;
-			
 			hideWhenEmpty = true;
 						
-			showCompletedTasks = 
-				Application.Preferences.GetBool (
-					Preferences.ShowCompletedTasksKey);
-			Application.Preferences.SettingChanged += OnSettingChanged;
-			
 			// TODO: Add a date time event watcher so that when we rollover to
 			// a new day, we can update the rangeStart and rangeEnd times.  The
 			// ranges will be used to determine whether tasks fit into certain
 			// groups in the main TaskWindow.  Reference Tomboy's NoteOfTheDay
 			// add-in for code that reacts on day changes.
-			
-			filteredTasks = new Gtk.TreeModelFilter (tasks, null);
-			filteredTasks.VisibleFunc = FilterTasks;
+
+			filteredTasks = CreateModel (rangeStart, rangeEnd, tasks);
+
+			filteredTasks.ShowCompletedTasks = 
+				Application.Preferences.GetBool (
+					Preferences.ShowCompletedTasksKey);
+			Application.Preferences.SettingChanged += OnSettingChanged;
 			
 			// TODO: Add something to watch events so that the group will
 			// automatically refilter and display/hide itself accordingly.
@@ -167,12 +158,12 @@ namespace Tasque
 		/// </value>
 		public DateTime TimeRangeStart
 		{
-			get { return timeRangeStart; }
+			get { return filteredTasks.TimeRangeStart; }
 			set {
-				if (value == timeRangeStart)
+				if (value == filteredTasks.TimeRangeStart)
 					return;
 				
-				timeRangeStart = value;
+				filteredTasks.SetRange (value, filteredTasks.TimeRangeEnd);
 				Refilter ();
 			}
 		}
@@ -182,12 +173,12 @@ namespace Tasque
 		/// </value>
 		public DateTime TimeRangeEnd
 		{
-			get { return timeRangeEnd; }
+			get { return filteredTasks.TimeRangeEnd; }
 			set {
-				if (value == timeRangeEnd)
+				if (value == filteredTasks.TimeRangeEnd)
 					return;
 				
-				timeRangeEnd = value;
+				filteredTasks.SetRange (filteredTasks.TimeRangeStart, value);
 				Refilter ();
 			}
 		}
@@ -333,7 +324,7 @@ namespace Tasque
 			base.OnRealized ();
 			
 			if (treeView.GetNumberOfTasks () == 0
-					&& (!showCompletedTasks || hideWhenEmpty))
+					&& (!filteredTasks.ShowCompletedTasks || hideWhenEmpty))
 				Hide ();
 			else
 				Show ();
@@ -345,65 +336,11 @@ namespace Tasque
 			header.Markup = GetHeaderMarkup (DisplayName);
 		}
 
-
-        /// <summary>
-        /// Filter out tasks that don't fit within the group's date range
-        /// </summary>
-		protected virtual bool FilterTasks (Gtk.TreeModel model, Gtk.TreeIter iter)
+		protected virtual  TaskGroupModel CreateModel (DateTime rangeStart,
+		                                               DateTime rangeEnd,
+		                                               TreeModel tasks)
 		{
-			ITask task = model.GetValue (iter, 0) as ITask;
-			if (task == null)
-				return false;
-			
-			// Do something special when task.DueDate == DateTime.MinValue since
-			// these tasks should always be in the very last category.
-			if (task.DueDate == DateTime.MinValue) {
-				if (timeRangeEnd == DateTime.MaxValue) {
-					if (!ShowCompletedTask (task))
-						return false;
-					
-					return true;
-				} else {
-					return false;
-				}
-			}
-			
-			if (task.DueDate < timeRangeStart || task.DueDate > timeRangeEnd)
-				return false;
-			
-			if (!ShowCompletedTask (task))
-				return false;
-			
-			return true;
-		}
-		
-		private bool ShowCompletedTask (ITask task)
-		{
-			if (task.State == TaskState.Completed) {
-				if (!showCompletedTasks)
-					return false;
-				
-				// Only show completed tasks that are from "Today".  Once it's
-				// tomorrow, don't show completed tasks in this group and
-				// instead, show them in the Completed Tasks Group.
-				if (task.CompletionDate == DateTime.MinValue)
-					return false; // Just in case
-				
-				if (!IsToday (task.CompletionDate))
-					return false;
-			}
-			
-			return true;
-		}
-		
-		private bool IsToday (DateTime testDate)
-		{
-			DateTime today = DateTime.Now;
-			if (today.Year != testDate.Year
-					|| today.DayOfYear != testDate.DayOfYear)
-				return false;
-			
-			return true;
+			return new TaskGroupModel (rangeStart, rangeEnd, tasks);
 		}
 		
 		/// <summary>
@@ -483,7 +420,7 @@ namespace Tasque
 			//Logger.Debug ("TaskGroup (\"{0}\").OnNumberOfTasksChanged ()", DisplayName);
 			// Check to see whether this group should be hidden or shown.
 			if (treeView.GetNumberOfTasks () == 0
-					&& (!showCompletedTasks || hideWhenEmpty))
+					&& (!filteredTasks.ShowCompletedTasks || hideWhenEmpty))
 				Hide ();
 			else
 				Show ();
@@ -512,10 +449,10 @@ namespace Tasque
 			
 			bool newValue =
 				preferences.GetBool (Preferences.ShowCompletedTasksKey);
-			if (showCompletedTasks == newValue)
+			if (filteredTasks.ShowCompletedTasks == newValue)
 				return; // don't do anything if nothing has changed
 			
-			showCompletedTasks = newValue;
+			filteredTasks.ShowCompletedTasks = newValue;
 			
 			ICategory cat = GetSelectedCategory ();
 			if (cat != null)
diff --git a/src/TaskGroupModel.cs b/src/TaskGroupModel.cs
new file mode 100644
index 0000000..0e8cdb1
--- /dev/null
+++ b/src/TaskGroupModel.cs
@@ -0,0 +1,109 @@
+
+using System;
+
+using Gtk;
+
+namespace Tasque
+{
+	public class TaskGroupModel : TreeModelFilter
+	{
+		public bool ShowCompletedTasks
+		{
+			get { return showCompletedTasks; }
+			set {
+				showCompletedTasks = value;
+				base.Refilter ();
+			}
+		}
+
+		public DateTime TimeRangeStart
+		{
+			get { return timeRangeStart; }
+		}
+
+		public DateTime TimeRangeEnd
+		{
+			get { return timeRangeEnd; }
+		}
+		
+		public TaskGroupModel (DateTime rangeStart, DateTime rangeEnd,
+		                       Gtk.TreeModel tasks) : base (tasks, null)
+		{
+			this.timeRangeStart = rangeStart;
+			this.timeRangeEnd = rangeEnd;
+
+			base.VisibleFunc = FilterTasks;
+		}
+
+		public void SetRange (DateTime rangeStart, DateTime rangeEnd)
+		{
+			this.timeRangeStart = rangeStart;
+			this.timeRangeEnd = rangeEnd;
+			base.Refilter ();
+		}
+
+		/// <summary>
+	        /// Filter out tasks that don't fit within the group's date range
+	        /// </summary>
+		protected virtual bool FilterTasks (Gtk.TreeModel model, Gtk.TreeIter iter)
+		{
+			ITask task = model.GetValue (iter, 0) as ITask;
+			if (task == null || task.State == TaskState.Deleted)
+				return false;
+			
+			// Do something special when task.DueDate == DateTime.MinValue since
+			// these tasks should always be in the very last category.
+			if (task.DueDate == DateTime.MinValue) {
+				if (timeRangeEnd == DateTime.MaxValue) {
+					if (!ShowCompletedTask (task))
+						return false;
+					
+					return true;
+				} else {
+					return false;
+				}
+			}
+			
+			if (task.DueDate < timeRangeStart || task.DueDate > timeRangeEnd)
+				return false;
+			
+			if (!ShowCompletedTask (task))
+				return false;
+
+			return true;
+		}
+		
+		protected DateTime timeRangeStart;
+		protected DateTime timeRangeEnd;
+		protected bool showCompletedTasks = false;
+
+		private bool ShowCompletedTask (ITask task)
+		{
+			if (task.State == TaskState.Completed) {
+				if (!showCompletedTasks)
+					return false;
+				
+				// Only show completed tasks that are from "Today".  Once it's
+				// tomorrow, don't show completed tasks in this group and
+				// instead, show them in the Completed Tasks Group.
+				if (task.CompletionDate == DateTime.MinValue)
+					return false; // Just in case
+				
+				if (!IsToday (task.CompletionDate))
+					return false;
+			}
+			
+			return true;
+		}
+		
+		private bool IsToday (DateTime testDate)
+		{
+			DateTime today = DateTime.Now;
+			if (today.Year != testDate.Year
+					|| today.DayOfYear != testDate.DayOfYear)
+				return false;
+			
+			return true;
+		}
+	}
+}
diff --git a/src/TaskGroupModelFactory.cs b/src/TaskGroupModelFactory.cs
new file mode 100644
index 0000000..61e5819
--- /dev/null
+++ b/src/TaskGroupModelFactory.cs
@@ -0,0 +1,43 @@
+
+using System;
+
+using Gtk;
+
+namespace Tasque
+{
+	public static class TaskGroupModelFactory
+	{
+		public static TaskGroupModel CreateTodayModel (TreeModel tasks)
+		{
+			DateTime rangeStart = DateTime.Now;
+			rangeStart = new DateTime (rangeStart.Year, rangeStart.Month,
+									   rangeStart.Day, 0, 0, 0);
+			DateTime rangeEnd = DateTime.Now;
+			rangeEnd = new DateTime (rangeEnd.Year, rangeEnd.Month,
+									 rangeEnd.Day, 23, 59, 59);
+			return new TaskGroupModel (rangeStart, rangeEnd, tasks);
+		}
+
+		public static TaskGroupModel CreateOverdueModel (TreeModel tasks)
+		{
+			DateTime rangeStart = DateTime.MinValue;
+			DateTime rangeEnd = DateTime.Now.AddDays (-1);
+			rangeEnd = new DateTime (rangeEnd.Year, rangeEnd.Month, rangeEnd.Day,
+									 23, 59, 59);
+
+			return new TaskGroupModel (rangeStart, rangeEnd, tasks);
+		}
+
+		public static TaskGroupModel CreateTomorrowModel (TreeModel tasks)
+		{
+			DateTime rangeStart = DateTime.Now.AddDays (1);
+			rangeStart = new DateTime (rangeStart.Year, rangeStart.Month,
+									   rangeStart.Day, 0, 0, 0);
+			DateTime rangeEnd = DateTime.Now.AddDays (1);
+			rangeEnd = new DateTime (rangeEnd.Year, rangeEnd.Month,
+									 rangeEnd.Day, 23, 59, 59);
+
+			return new TaskGroupModel (rangeStart, rangeEnd, tasks);
+		}
+	}
+}
diff --git a/tasque.mdp b/tasque.mdp
index 9b02df3..8005cc5 100644
--- a/tasque.mdp
+++ b/tasque.mdp
@@ -1,4 +1,4 @@
-<Project name="tasque" fileversion="2.0" language="C#" clr-version="Net_2_0" ctype="DotNetProject">
+<Project name="tasque" fileversion="2.0" language="C#" clr-version="Net_2_0" targetFramework="2.0" ctype="DotNetProject">
   <Configurations active="Debug">
     <Configuration name="Debug" ctype="DotNetProjectConfiguration">
       <Output directory="bin/Debug" assembly="tasque" />
@@ -77,9 +77,12 @@
     <File name="src/Backends/Hiveminder/service/Group.cs" subtype="Code" buildaction="Compile" />
     <File name="src/Backends/Hiveminder/HmPreferencesWidget.cs" subtype="Code" buildaction="Compile" />
     <File name="src/Backends/Hiveminder/service/HiveminderException.cs" subtype="Code" buildaction="Compile" />
+    <File name="src/TaskGroupModel.cs" subtype="Code" buildaction="Compile" />
+    <File name="src/TaskGroupModelFactory.cs" subtype="Code" buildaction="Compile" />
+    <File name="src/CompletedTaskGroupModel.cs" subtype="Code" buildaction="Compile" />
   </Contents>
   <References>
-    <ProjectReference type="Gac" localcopy="True" refto="glib-sharp, Version=2.10.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
+    <ProjectReference type="Gac" localcopy="True" refto="glib-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
     <ProjectReference type="Gac" localcopy="True" refto="gdk-sharp, Version=2.10.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
     <ProjectReference type="Gac" localcopy="True" refto="gtk-sharp, Version=2.10.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
     <ProjectReference type="Gac" localcopy="True" refto="notify-sharp, Version=0.4.0.0, Culture=neutral, PublicKeyToken=2df29c54e245917a" />
@@ -92,7 +95,6 @@
     <ProjectReference type="Gac" localcopy="True" refto="Mono.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756" />
     <ProjectReference type="Gac" localcopy="True" refto="System.Xml, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
   </References>
-  <GtkDesignInfo />
   <MonoDevelop.Autotools.MakefileInfo IntegrationEnabled="True" RelativeMakefileName="Makefile.am" ExecuteTargetName="run" IsAutotoolsProject="True" RelativeConfigureInPath=".">
     <BuildFilesVar />
     <DeployFilesVar />



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