[tasque/viewmodel: 2/78] Still work in progress.



commit 6369285cd3d553f58820aeff1d05801e72e0d36e
Author: Antonius Riha <antoniusriha gmail com>
Date:   Fri Jul 13 03:09:42 2012 +0200

    Still work in progress.

 src/libtasque/Backend.cs                           |  271 ++++++++++++--------
 src/libtasque/Category.cs                          |   48 ++--
 src/libtasque/IBackendPreferences.cs               |    2 +-
 src/libtasque/INote.cs                             |   19 --
 src/libtasque/NotifyCollection.cs                  |  142 ++++++++++
 src/libtasque/ReadOnlyNotifyCollection.cs          |   97 +++++++
 src/libtasque/Task.cs                              |  191 +++++---------
 .../TaskCompletionDateComparer.cs}                 |   66 +++---
 src/libtasque/{ICategory.cs => TaskNote.cs}        |   11 +-
 src/libtasque/{ICategory.cs => TaskNoteSupport.cs} |   18 +-
 src/libtasque/TaskState.cs                         |   34 ++-
 src/libtasque/libtasque.csproj                     |    9 +-
 src/tasque/Application.cs                          |    8 +-
 src/tasque/Backends/Dummy/DummyBackend.cs          |  162 +++---------
 src/tasque/Backends/Dummy/DummyNote.cs             |   44 ++--
 src/tasque/Backends/Dummy/DummyTask.cs             |  158 +++++-------
 src/tasque/Backends/Hiveminder/HmBackend.cs        |    8 +-
 src/tasque/Backends/Hiveminder/HmCategory.cs       |    2 +-
 src/tasque/Backends/Hiveminder/HmNote.cs           |    2 +-
 src/tasque/Backends/Hiveminder/HmTask.cs           |   14 +-
 src/tasque/Backends/Rtm/RtmBackend.cs              |   12 +-
 src/tasque/Backends/Rtm/RtmCategory.cs             |    2 +-
 src/tasque/Backends/Rtm/RtmNote.cs                 |    2 +-
 src/tasque/Backends/Rtm/RtmTask.cs                 |   14 +-
 src/tasque/Backends/Sqlite/SqliteBackend.cs        |    8 +-
 src/tasque/Backends/Sqlite/SqliteCategory.cs       |    2 +-
 src/tasque/Backends/Sqlite/SqliteNote.cs           |    2 +-
 src/tasque/Backends/Sqlite/SqliteTask.cs           |   12 +-
 src/tasque/CompletedTaskGroup.cs                   |    8 +-
 src/tasque/NoteDialog.cs                           |    4 +-
 src/tasque/NoteWidget.cs                           |    6 +-
 src/tasque/PreferencesDialog.cs                    |   12 +-
 src/tasque/RemoteControl.cs                        |   14 +-
 src/tasque/TaskGroup.cs                            |   10 +-
 src/tasque/TaskTreeView.cs                         |    4 +-
 src/tasque/TaskWindow.cs                           |   50 ++--
 src/tasque/tasque.csproj                           |    2 +-
 37 files changed, 801 insertions(+), 669 deletions(-)
---
diff --git a/src/libtasque/Backend.cs b/src/libtasque/Backend.cs
index 1772e7c..d23eeba 100644
--- a/src/libtasque/Backend.cs
+++ b/src/libtasque/Backend.cs
@@ -1,7 +1,7 @@
 // ITaskBackend.cs created with MonoDevelop
 // User: boyd at 7:02 AMÂ2/11/2008
 // 
-// IBackend.cs
+// Backend.cs
 //  
 // Author:
 //       Antonius Riha <antoniusriha gmail com>
@@ -25,97 +25,57 @@
 // 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.Collections;
-using System.Collections.ObjectModel;
-using CollectionTransforms;
-using Tasque;
-using System.ComponentModel;
 using System;
 using System.Collections.Generic;
+using System.Collections.Specialized;
 
 namespace Tasque
 {
-	public delegate void BackendInitializedHandler ();
-	public delegate void BackendSyncStartedHandler ();
-	public delegate void BackendSyncFinishedHandler ();
-	
 	/// <summary>
 	/// This is the main integration interface for different backends that
 	/// Tasque can use.
 	/// </summary>
 	public abstract class Backend
 	{
-		protected Backend ()
+		protected Backend (string name)
 		{
-			tasks = new ObservableCollection<Task> ();
-			Tasks = new ReadOnlyObservableCollection<Task> (tasks);
-			var cvTasks = new CollectionView<Task> (Tasks);
-			/*
-			 * this invokes the default comparer, which in turn
-			 * will use the IComparable implmentation of Task
-			 */
-			cvTasks.SortDescriptions.Add (new SortDescription ());
-			SortedTasks = cvTasks;
-			
-			Categories = new ObservableCollection<ICategory> ();
-			var cvCategories = new CollectionView<ICategory> (Categories);
-			cvCategories.SortDescriptions.Add (new SortDescription ());
-			SortedCategories = cvCategories;
-		}
-		
-		public abstract event BackendInitializedHandler BackendInitialized;
-		public abstract event BackendSyncStartedHandler BackendSyncStarted;
-		public abstract event BackendSyncFinishedHandler BackendSyncFinished;
+			if (name == null)
+				throw new ArgumentNullException ("name");
 
-		#region Properties
-		/// <value>
-		/// A human-readable name for the backend that will be displayed in the
-		/// preferences dialog to allow the user to select which backend Tasque
-		/// should use.
-		/// </value>
-		public abstract string Name {
-			get;
+			Name = name;
+
+			tasks = new NotifyCollection<Task> ();
+			Tasks = new ReadOnlyNotifyCollection<Task> (tasks);
+
+			categoriesChangedSources = new List<INotifyCollectionChanged> ();
+			Categories = new NotifyCollection<Category> ();
+			Categories.CollectionChanged += HandleCategoriesChanged;
 		}
-		
-		/// <value>
-		/// All the tasks provided by the backend.
-		/// </value>
-		public ReadOnlyObservableCollection<Task> Tasks {	get; }
 
-		public abstract IEnumerable SortedTasks { get; }
-		
+		#region Properties
 		/// <value>
 		/// This returns all the ICategory items from the backend.
 		/// </value>
-		public abstract ObservableCollection<ICategory> Categories { get; }
-		
-		public abstract IEnumerable SortedCategories { get;	}
-		
-		public ICategory DefaultCategory {
-			get { return defaultCategory; }
-			set {
-				if (value == null)
-					throw new ArgumentNullException ("value");
-				
-				defaultCategory = value;
-			}
-		}
-		
+		public NotifyCollection<Category> Categories { get; private set; }
+
 		/// <value>
 		/// Indication that the backend has enough information
 		/// (credentials/etc.) to run.  If false, the properties dialog will
 		/// be shown so the user can configure the backend.
 		/// </value>
-		public abstract bool Configured {
-			get;
-		}
-		
+		public abstract bool Configured { get; }
+
 		/// <value>
 		/// Inidication that the backend is initialized
 		/// </value>
-		public abstract bool Initialized {
-			get;
-		}
+		public abstract bool Initialized { get; }
+
+		/// <value>
+		/// A human-readable name for the backend that will be displayed in the
+		/// preferences dialog to allow the user to select which backend Tasque
+		/// should use.
+		/// </value>
+		public string Name { get; private set; }
 		
 		/// <summary>
 		/// An object that provides a means of managing backend specific preferences.
@@ -124,74 +84,159 @@ namespace Tasque
 		/// A <see cref="Tasque.Backends.BackendPreferences"/>
 		/// </returns>
 		public abstract IBackendPreferences Preferences { get; }
-		#endregion // Properties
+
+		/// <value>
+		/// All the tasks provided by the backend.
+		/// </value>
+		public ReadOnlyNotifyCollection<Task> Tasks { get; private set; }
+		#endregion
 		
 		#region Methods
-		public Task CreateTask (string taskName)
-		{
-			CreateTask (taskName, null);
-		}
-		
+		/// <summary>
+		/// Cleanup the backend before quitting
+		/// </summary>
+		public abstract void Cleanup ();
+
 		/// <summary>
 		/// Create a new task.
 		/// </summary>
-		public Task CreateTask (string taskName, ICategory category)
+		public Task CreateTask (string taskName, Category category)
 		{
-			return CreateTask (taskName, new ICategory [] { category });
+			if (category == null)
+				throw new ArgumentNullException ("category");
+
+			return CreateTask (taskName, new Category [] { category });
 		}
 		
-		public Task CreateTask (string taskName, IEnumerable<ICategory> categories)
+		public Task CreateTask (string taskName, IEnumerable<Category> categories)
 		{
+			if (taskName == null)
+				throw new ArgumentNullException ("taskName");
+			if (categories == null)
+				throw new ArgumentNullException ("categories");
+
+			var task = CreateTaskCore (taskName);
+
+			bool isEmpty = true;
+			foreach (var cat in categories) {
+				if (cat == null)
+					throw new ArgumentException ("One of the provided categories is null.","categories");
 
+				cat.Add (task);
+				isEmpty = false;
+			}
+
+			if (isEmpty)
+				throw new ArgumentException ("This backend doesn't contain a category. Hence it's " +
+					"impossible to add an item.", "categories");
+
+			return task;
 		}
-		
-		/// <summary>
-		/// Deletes the specified task.
-		/// </summary>
-		/// <param name="task">
-		/// A <see cref="ITask"/>
-		/// </param>
-		public abstract void DeleteTask (Task task);
-		
-		/// <summary>
-		/// Refreshes the backend.
-		/// </summary>
-		public abstract void Refresh ();
-		
+
 		/// <summary>
 		/// Initializes the backend
 		/// </summary>
 		public abstract void Initialize ();
 
 		/// <summary>
-		/// Cleanup the backend before quitting
+		/// Refreshes the backend.
 		/// </summary>
-		public abstract void Cleanup ();
-		#endregion // Methods
+		public abstract void Refresh ();
+
+		protected abstract Task CreateTaskCore (string taskName);
+
+		protected void OnBackendInitialized () {
+			if (BackendInitialized != null)
+				BackendInitialized (this, EventArgs.Empty);
+		}
+
+		protected void OnBackendSyncFinished () {
+			if (BackendSyncFinished != null)
+				BackendSyncFinished (this, EventArgs.Empty);
+		}
+
+		protected void OnBackendSyncStarted () {
+			if (BackendSyncStarted != null)
+				BackendSyncStarted (this, EventArgs.Empty);
+		}
+		#endregion
+
+		public event EventHandler BackendInitialized;
+		public event EventHandler BackendSyncFinished;
+		public event EventHandler BackendSyncStarted;
 		
-		protected void AddTask (Task task, IEnumerable<ICategory> categories)
+		void HandleCategoriesChanged (object sender, NotifyCollectionChangedEventArgs e)
 		{
-			if (Categories.Count == 0)
-				throw new InvalidOperationException ("Cannot add a task to a backend " +
-					"which doesn't have any categories defined.");
-			if (categories == null)
-				throw new ArgumentNullException ("categories");
-			if (task == null)
-				throw new ArgumentNullException ("task");
-			
-			foreach (var cat in categories) {
-				if (cat == null)
-					cat = DefaultCategory;
-				
-				if (!Categories.Contains (cat))
-					throw new ArgumentException (string.Format (
-						"The provided category {0} has not been added to this backend.", cat.Name));
-				
-				
+			switch (e.Action) {
+			case NotifyCollectionChangedAction.Add: {
+				var cat = (Category)e.NewItems [0];
+				RegisterCategoriesChanged (cat);
+				foreach (var item in cat)
+					tasks.Add (item);
+				break;
+			}
+			case NotifyCollectionChangedAction.Remove: {
+				var cat = (Category)e.OldItems [0];
+				UnRegisterCategoriesChanged (cat);
+				RemoveCategoryContent (cat);
+				break;
+			}
+			case NotifyCollectionChangedAction.Reset:
+				for (int i = 0; i < categoriesChangedSources.Count; i++) {
+					UnRegisterCategoriesChanged (categoriesChangedSources [0]);
+				}
+				tasks.Clear ();
+				break;
 			}
 		}
-		
-		ICategory defaultCategory;
-		ObservableCollection<Task> tasks;
+
+		void HandleTaskCollectionChanged (object sender, NotifyCollectionChangedEventArgs e)
+		{
+			switch (e.Action) {
+			case NotifyCollectionChangedAction.Add:
+				tasks.Add ((Task)e.NewItems [0]);
+				break;
+			case NotifyCollectionChangedAction.Remove:
+				var task = (Task)e.OldItems [0];
+				if (IsSoleOccurenceInCategory ((Category)sender, task))
+					tasks.Remove (task);
+				break;
+			case NotifyCollectionChangedAction.Reset:
+				RemoveCategoryContent ((Category)sender);
+				break;
+			}
+		}
+
+		bool IsSoleOccurenceInCategory (Category cat, Task task)
+		{
+			foreach (var item in Categories) {
+				if (cat != item && cat.Contains (task))
+					return false;
+			}
+			return true;
+		}
+
+		void RemoveCategoryContent (Category cat)
+		{
+			foreach (var item in cat) {
+				if (IsSoleOccurenceInCategory (cat, item))
+					tasks.Remove (item);
+			}
+		}
+
+		void RegisterCategoriesChanged (INotifyCollectionChanged source)
+		{
+			categoriesChangedSources.Add (source);
+			source.CollectionChanged += HandleCategoriesChanged;
+		}
+
+		void UnRegisterCategoriesChanged (INotifyCollectionChanged source)
+		{
+			source.CollectionChanged -= HandleCategoriesChanged;
+			categoriesChangedSources.Remove (source);
+		}
+
+		List<INotifyCollectionChanged> categoriesChangedSources;
+		NotifyCollection<Task> tasks;
 	}
 }
diff --git a/src/libtasque/Category.cs b/src/libtasque/Category.cs
index 39b81d4..49d3355 100644
--- a/src/libtasque/Category.cs
+++ b/src/libtasque/Category.cs
@@ -24,41 +24,51 @@
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 // THE SOFTWARE.
 using System;
-using System.Collections.ObjectModel;
-using System.Collections;
+using System.ComponentModel;
 
 namespace Tasque
 {
-	public class Category : ObservableCollection<Task>, ICategory
+	public class Category : NotifyCollection<Task>, IComparable<Category>, INotifyPropertyChanged
 	{
-		public Category (string name, Backend backend)
+		public Category (string name)
 		{
-			if (backend == null)
-				throw new ArgumentNullException ("backend");
-			if (name == null)
-				throw new ArgumentNullException ("name");
-			
 			Name = name;
-			this.backend = backend;
 		}
 
-		public bool IsReadOnly { get { return false; } }
-		
-		public string Name { get; private set; }
+		public string Name {
+			get { return name; }
+			set {
+				if (value == null)
+					throw new ArgumentNullException ("name");
+
+				if (value == name) {
+					name = value;
+					OnNameChanged ();
+					OnPropertyChanged ("Name");
+				}
+			}
+		}
 		
-		public virtual int CompareTo (ICategory other)
+		public virtual int CompareTo (Category other)
 		{
 			if (other == null)
 				return 1;
 			
 			return Name.CompareTo (other.Name);
 		}
-		
-		IEnumerator IEnumerable.GetEnumerator ()
+
+		#region INotifyPropertyChanged implementation
+		public event PropertyChangedEventHandler PropertyChanged;
+		#endregion
+
+		protected virtual void OnNameChanged () {}
+
+		protected void OnPropertyChanged (string propertyName)
 		{
-			return GetEnumerator ();
+			if (PropertyChanged != null)
+				PropertyChanged (this, new PropertyChangedEventArgs (propertyName));
 		}
-		
-		Backend backend;
+
+		string name;
 	}
 }
diff --git a/src/libtasque/IBackendPreferences.cs b/src/libtasque/IBackendPreferences.cs
index 8154eb7..969402a 100644
--- a/src/libtasque/IBackendPreferences.cs
+++ b/src/libtasque/IBackendPreferences.cs
@@ -24,7 +24,7 @@
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 // THE SOFTWARE.
 
-namespace Tasque.Backends
+namespace Tasque
 {
 	public interface IBackendPreferences
 	{
diff --git a/src/libtasque/NotifyCollection.cs b/src/libtasque/NotifyCollection.cs
new file mode 100644
index 0000000..50d2964
--- /dev/null
+++ b/src/libtasque/NotifyCollection.cs
@@ -0,0 +1,142 @@
+// 
+// NotifyCollection.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;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Collections.Specialized;
+using System.ComponentModel;
+
+namespace Tasque
+{
+	public class NotifyCollection<T> : ICollection<T>, INotifyCollectionChanged
+		where T : INotifyPropertyChanged, IComparable<T>
+	{
+		public NotifyCollection ()
+		{
+			items = new ObservableCollection<T> ();
+		}
+
+		#region IEnumerable implementation
+		IEnumerator IEnumerable.GetEnumerator ()
+		{
+			return GetEnumerator ();
+		}
+
+		public IEnumerator<T> GetEnumerator ()
+		{
+			return items.GetEnumerator ();
+		}
+		#endregion
+
+		#region ICollection implementation
+		public void Add (T item)
+		{
+			if (item == null)
+				throw new ArgumentNullException ("item");
+
+			if (items.Contains (item))
+				return;
+
+			item.PropertyChanged += HandlePropertyChanged;
+
+			OnAdd (item);
+			var index = GetItemIndex (item);
+			items.Insert (index, item);
+		}
+
+		public void Clear ()
+		{
+			OnClear ();
+
+			foreach (var item in items)
+				item.PropertyChanged -= HandlePropertyChanged;
+
+			items.Clear ();
+		}
+
+		public bool Contains (T item)
+		{
+			return items.Contains (item);
+		}
+
+		public void CopyTo (T[] array, int arrayIndex)
+		{
+			items.CopyTo (array, arrayIndex);
+		}
+
+		public bool Remove (T item)
+		{
+			if (Contains (item)) {
+				OnRemove (item);
+				item.PropertyChanged -= HandlePropertyChanged;
+			}
+
+			return items.Remove (item);
+		}
+
+		public int Count { get { return items.Count; } }
+
+		public bool IsReadOnly { get { return false; } }
+		#endregion
+
+		#region INotifyCollectionChanged implementation
+		public event NotifyCollectionChangedEventHandler CollectionChanged {
+			add { items.CollectionChanged += value; }
+			remove { items.CollectionChanged -= value; }
+		}
+		#endregion
+
+		protected virtual void OnAdd (T item) {}
+
+		protected virtual void OnClear () {}
+
+		protected virtual void OnRemove (T item) {}
+
+		void HandlePropertyChanged (object sender, PropertyChangedEventArgs e)
+		{
+			var item = (T)sender;
+			var oldIndex = items.IndexOf (item);
+			var newIndex = GetItemIndex (item);
+
+			if (oldIndex != newIndex)
+				items.Move (oldIndex, newIndex);
+		}
+
+		int GetItemIndex (T item)
+		{
+			var index = 0;
+			foreach (var i in items) {
+				if (item.CompareTo (i) == -1)
+					break;
+				index++;
+			}
+			return index;
+		}
+
+		ObservableCollection<T> items;
+	}
+}
diff --git a/src/libtasque/ReadOnlyNotifyCollection.cs b/src/libtasque/ReadOnlyNotifyCollection.cs
new file mode 100644
index 0000000..a6185e2
--- /dev/null
+++ b/src/libtasque/ReadOnlyNotifyCollection.cs
@@ -0,0 +1,97 @@
+// 
+// ReadOnlyNotifyCollection.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;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.ComponentModel;
+
+namespace Tasque
+{
+	public class ReadOnlyNotifyCollection<T> : ICollection<T>, INotifyCollectionChanged
+		where T : INotifyPropertyChanged, IComparable<T>
+	{
+		public ReadOnlyNotifyCollection (NotifyCollection<T> source)
+		{
+			if (source == null)
+				throw new ArgumentNullException ("source");
+
+			items = source;
+		}
+
+		#region IEnumerable implementation
+		IEnumerator IEnumerable.GetEnumerator ()
+		{
+			return GetEnumerator ();
+		}
+
+		public IEnumerator<T> GetEnumerator ()
+		{
+			return items.GetEnumerator ();
+		}
+		#endregion
+
+		#region ICollection implementation
+		void ICollection<T>.Add (T item)
+		{
+			throw new NotSupportedException ("This collection is read-only.");
+		}
+
+		void ICollection<T>.Clear ()
+		{
+			throw new NotSupportedException ("This collection is read-only.");
+		}
+
+		public bool Contains (T item)
+		{
+			return items.Contains (item);
+		}
+
+		public void CopyTo (T[] array, int arrayIndex)
+		{
+			items.CopyTo (array, arrayIndex);
+		}
+
+		bool ICollection<T>.Remove (T item)
+		{
+			throw new NotSupportedException ("This collection is read-only.");
+		}
+
+		public int Count { get { return items.Count; } }
+
+		public bool IsReadOnly { get { return true; } }
+		#endregion
+
+		#region INotifyCollectionChanged implementation
+		public event NotifyCollectionChangedEventHandler CollectionChanged {
+			add { items.CollectionChanged += value; }
+			remove { items.CollectionChanged -= value; }
+		}
+		#endregion
+
+		NotifyCollection<T> items;
+	}
+}
diff --git a/src/libtasque/Task.cs b/src/libtasque/Task.cs
index 411808d..3c35927 100644
--- a/src/libtasque/Task.cs
+++ b/src/libtasque/Task.cs
@@ -1,7 +1,5 @@
-// AbstractTask.cs created with MonoDevelop
-// User: boyd at 6:52 AMÂ2/12/2008
 // 
-// AbstractTask.cs
+// Task.cs
 //  
 // Author:
 //       Antonius Riha <antoniusriha gmail com>
@@ -26,7 +24,7 @@
 // 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.Collections.ObjectModel;
 using System.ComponentModel;
 
 namespace Tasque
@@ -35,90 +33,66 @@ namespace Tasque
 	{
 		protected Task (string name)
 		{
-			if (name == null)
-				throw new ArgumentNullException ("name");
-			
 			Name = name;
 		}
 		
-		uint timerID = 0;
-		
 		#region Properties
-		public abstract string Id
-		{
-			get; 
-		}
+		public string Name {
+			get { return name; }
+			set {
+				if (value == null)
+					throw new ArgumentNullException ("name");
 
-		public string Name { get; set; }
-		
-		public abstract DateTime DueDate {
-			get;
-			set;
-		}
-		
-		public abstract DateTime CompletionDate
-		{
-			get;
-			set;
-		}
-		
-		public abstract bool IsComplete 
-		{
-			get;
-		}
-		
-		public abstract TaskPriority Priority
-		{
-			get;
-			set;
-		}
-		
-		public abstract bool HasNotes
-		{
-			get;
-		}
-		
-		public abstract bool SupportsMultipleNotes
-		{
-			get;
+				if (value != name) {
+					name = value;
+					OnNameChanged ();
+					OnPropertyChanged ("Name");
+				}
+			}
 		}
 		
-		public abstract TaskState State
-		{
-			get;
-		}
+		public abstract DateTime DueDate { get; set; }
 		
-		public abstract List<INote> Notes
-		{
-			get;
-		}
+		public abstract DateTime CompletionDate { get; set; }
 
-		/// <value>
-		/// The ID of the timer used to complete a task after being marked
-		/// inactive.
-		/// </value>
-		public uint TimerID
-		{
-			get { return timerID; }
-			set { timerID = value; }
-		}		
-		#endregion // Properties
+		public bool HasNotes { get { return Notes.Count > 0; } }
+
+		public bool IsComplete { get { return State == TaskState.Completed; } }
+
+		public bool IsCompletionDateSet { get { return CompletionDate != DateTime.MinValue; } }
+
+		public bool IsDueDateSet { get { return DueDate != DateTime.MinValue; } }
+
+		public abstract ReadOnlyObservableCollection<TaskNote> Notes { get; }
+
+		public abstract TaskPriority Priority { get; set; }
+
+		public abstract TaskState State { get; }
+
+		public abstract TaskNoteSupport TaskNoteSupport { get; }
+		#endregion
 		
 		#region Methods
-		
 		public abstract void Activate ();
-		public abstract void Inactivate ();
-		public abstract void Complete ();
-		public abstract void Delete ();
-		public abstract INote CreateNote(string text);
-		public abstract void DeleteNote(INote note);
-		public abstract void SaveNote(INote note);		
-		
+
+		public void AddNote (TaskNote note)
+		{
+			if (note == null)
+				throw new ArgumentNullException ("note");
+
+			if (Notes.Contains (note))
+				return;
+
+			OnAddNote ();
+		}
+
 		public int CompareTo (Task task)
 		{
+			if (task == null)
+				return 1;
+
 			bool isSameDate = true;
-			if (DueDate.Year != task.DueDate.Year
-					|| DueDate.DayOfYear != task.DueDate.DayOfYear)
+			if (DueDate.Year != task.DueDate.Year || DueDate.DayOfYear != task.DueDate.DayOfYear)
 				isSameDate = false;
 			
 			if (!isSameDate) {
@@ -134,56 +108,36 @@ namespace Tasque
 				
 				int result = DueDate.CompareTo (task.DueDate);
 				
-				if (result != 0) {
+				if (result != 0)
 					return result;
-				}
 			}
 			
 			// The due dates match, so now sort based on priority and name
-			return CompareByPriorityAndName (task);
+			return CompareToByPriorityAndName (task);
 		}
-		
-		public int CompareToByCompletionDate (Task task)
-		{
-			bool isSameDate = true;
-			if (CompletionDate.Year != task.CompletionDate.Year
-					|| CompletionDate.DayOfYear != task.CompletionDate.DayOfYear)
-				isSameDate = false;
-			
-			if (!isSameDate) {
-				if (CompletionDate == DateTime.MinValue) {
-					// No completion date set for some reason.  Since we already
-					// tested to see if the dates were the same above, we know
-					// that the passed-in task has a CompletionDate set, so the
-					// passed-in task should be "higher" in the sort.
-					return 1;
-				} else if (task.CompletionDate == DateTime.MinValue) {
-					// "this" task has a completion date and should evaluate
-					// higher than the passed-in task which doesn't have a
-					// completion date.
-					return -1;
-				}
-				
-				return CompletionDate.CompareTo (task.CompletionDate);
-			}
-			
-			// The completion dates are the same, so no sort based on other
-			// things.
-			return CompareByPriorityAndName (task);
-		}
-		#endregion // Methods
 
-		public event PropertyChangedEventHandler PropertyChanged;
+		public abstract void Complete ();
+
+		public abstract TaskNote CreateNote(string text);
+
+		public abstract void Delete ();
+
+		public abstract bool DeleteNote(TaskNote note);
+
+		protected abstract void OnAddNote ();
+
+		protected virtual void OnNameChanged () {}
 
 		protected void OnPropertyChanged (string propertyName)
 		{
 			if (PropertyChanged != null)
 				PropertyChanged (this, new PropertyChangedEventArgs (propertyName));
 		}
-		
-		#region Private Methods
-		
-		int CompareByPriorityAndName (Task task)
+		#endregion
+
+		public event PropertyChangedEventHandler PropertyChanged;
+
+		internal int CompareToByPriorityAndName (Task task)
 		{
 			// The due dates match, so now sort based on priority
 			if (Priority != task.Priority) {
@@ -191,17 +145,15 @@ namespace Tasque
 				case TaskPriority.High:
 					return -1;
 				case TaskPriority.Medium:
-					if (task.Priority == TaskPriority.High) {
+					if (task.Priority == TaskPriority.High)
 						return 1;
-					} else {
+					else
 						return -1;
-					}
 				case TaskPriority.Low:
-					if (task.Priority == TaskPriority.None) {
+					if (task.Priority == TaskPriority.None)
 						return -1;
-					} else {
+					else
 						return 1;
-					}
 				case TaskPriority.None:
 					return 1;
 				}
@@ -210,8 +162,7 @@ namespace Tasque
 			// Due dates and priorities match, now sort by name
 			return Name.CompareTo (task.Name);
 		}
-		#endregion // Private Methods
-		
-		Backend backend;
+
+		string name;
 	}
 }
diff --git a/src/tasque/AllCategory.cs b/src/libtasque/TaskCompletionDateComparer.cs
similarity index 51%
rename from src/tasque/AllCategory.cs
rename to src/libtasque/TaskCompletionDateComparer.cs
index 45f6dac..247cc36 100644
--- a/src/tasque/AllCategory.cs
+++ b/src/libtasque/TaskCompletionDateComparer.cs
@@ -1,7 +1,5 @@
-// AllCategory.cs created with MonoDevelop
-// User: boyd at 3:45 PMÂ2/12/2008
 // 
-// AllCategory.cs
+// TaskCompletionDateComparer.cs
 //  
 // Author:
 //       Antonius Riha <antoniusriha gmail com>
@@ -25,42 +23,46 @@
 // 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 Mono.Unix;
-using System.ComponentModel;
 
 namespace Tasque
 {
-	public class AllCategory : Category
+	public class TaskCompletionDateComparer : Comparer<Task>
 	{
-		// A "set" of categories specified by the user to show when the "All"
-		// category is selected in the TaskWindow.  If the list is empty, tasks
-		// from all categories will be shown.  Otherwise, only tasks from the
-		// specified lists will be shown.
-		List<string> categoriesToHide;
-		
-		public AllCategory () : base ("All")
+		public override int Compare (Task x, Task y)
 		{
-			Preferences preferences = Application.Preferences;
-			categoriesToHide =
-				preferences.GetStringList (Preferences.HideInAllCategory);
-			Application.Preferences.SettingChanged += OnSettingChanged;
-		}
-		
-		void OnSettingChanged (Preferences preferences, string settingKey)
-		{
-			if (settingKey.CompareTo (Preferences.HideInAllCategory) != 0)
-				return;
-			
-			categoriesToHide =
-				preferences.GetStringList (Preferences.HideInAllCategory);
-		}
+			if (x == null && y == null)
+				return 0;
+			else if (x == null)
+				return -1;
+			else if (y == null)
+				return 1;
 
-		#region IComparable implementation
-		public override int CompareTo (ICategory other)
-		{
-			return -1;
+			bool isSameDate = true;
+			if (x.CompletionDate.Year != y.CompletionDate.Year
+			    || x.CompletionDate.DayOfYear != y.CompletionDate.DayOfYear)
+				isSameDate = false;
+			
+			if (!isSameDate) {
+				if (x.CompletionDate == DateTime.MinValue) {
+					// No completion date set for some reason.  Since we already
+					// tested to see if the dates were the same above, we know
+					// that the passed-in task has a CompletionDate set, so the
+					// passed-in task should be "higher" in the sort.
+					return 1;
+				} else if (y.CompletionDate == DateTime.MinValue) {
+					// "this" task has a completion date and should evaluate
+					// higher than the passed-in task which doesn't have a
+					// completion date.
+					return -1;
+				}
+				
+				return x.CompletionDate.CompareTo (y.CompletionDate);
+			}
+			
+			// The completion dates are the same, so no sort based on other things.
+			return x.CompareToByPriorityAndName (y);
 		}
-		#endregion
 	}
 }
diff --git a/src/libtasque/ICategory.cs b/src/libtasque/TaskNote.cs
similarity index 83%
copy from src/libtasque/ICategory.cs
copy to src/libtasque/TaskNote.cs
index efa9d59..a20b55c 100644
--- a/src/libtasque/ICategory.cs
+++ b/src/libtasque/TaskNote.cs
@@ -4,7 +4,7 @@
 // To change standard headers go to Edit->Preferences->Coding->Standard Headers
 //
 // 
-// ICategory.cs
+// TaskNote.cs
 //  
 // Author:
 //       Antonius Riha <antoniusriha gmail com>
@@ -28,16 +28,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 System;
-using System.ComponentModel;
-using System.Collections.Specialized;
-using System.Collections.Generic;
 
 namespace Tasque
 {
-	public interface ICategory : ICollection<Task>, IComparable<ICategory>,
-		INotifyPropertyChanged,	INotifyCollectionChanged
+	public abstract class TaskNote
 	{
-		string Name	{ get; }
+		public abstract string Text { get; set; }
 	}
 }
diff --git a/src/libtasque/ICategory.cs b/src/libtasque/TaskNoteSupport.cs
similarity index 73%
rename from src/libtasque/ICategory.cs
rename to src/libtasque/TaskNoteSupport.cs
index efa9d59..bdf4a52 100644
--- a/src/libtasque/ICategory.cs
+++ b/src/libtasque/TaskNoteSupport.cs
@@ -1,10 +1,5 @@
-// ICategory.cs created with MonoDevelop
-// User: boyd at 9:04 AMÂ2/11/2008
-//
-// To change standard headers go to Edit->Preferences->Coding->Standard Headers
-//
 // 
-// ICategory.cs
+// TaskNoteSupport.cs
 //  
 // Author:
 //       Antonius Riha <antoniusriha gmail com>
@@ -28,16 +23,13 @@
 // 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.ComponentModel;
-using System.Collections.Specialized;
-using System.Collections.Generic;
 
 namespace Tasque
 {
-	public interface ICategory : ICollection<Task>, IComparable<ICategory>,
-		INotifyPropertyChanged,	INotifyCollectionChanged
+	public enum TaskNoteSupport
 	{
-		string Name	{ get; }
+		None,
+		Single,
+		Multiple
 	}
 }
diff --git a/src/libtasque/TaskState.cs b/src/libtasque/TaskState.cs
index 41ffa11..fb47009 100644
--- a/src/libtasque/TaskState.cs
+++ b/src/libtasque/TaskState.cs
@@ -1,7 +1,30 @@
 // TaskState.cs created with MonoDevelop
 // User: boyd at 8:37 AMÂ2/12/2008
-
-using System;
+// 
+// TaskState.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.
 
 namespace Tasque
 {
@@ -13,13 +36,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/libtasque/libtasque.csproj b/src/libtasque/libtasque.csproj
index 657767f..8ea27c5 100644
--- a/src/libtasque/libtasque.csproj
+++ b/src/libtasque/libtasque.csproj
@@ -128,8 +128,6 @@
     </CustomCommands>
   </PropertyGroup>
   <ItemGroup>
-    <Compile Include="ICategory.cs" />
-    <Compile Include="INote.cs" />
     <Compile Include="TaskPriority.cs" />
     <Compile Include="TaskState.cs" />
     <Compile Include="TaskParser.cs" />
@@ -159,10 +157,15 @@
     </Compile>
     <Compile Include="NativeApplication.cs" />
     <Compile Include="IBackendPreferences.cs" />
-    <Compile Include="Category.cs" />
     <Compile Include="Backend.cs" />
     <Compile Include="InternetMode.cs" />
     <Compile Include="Task.cs" />
+    <Compile Include="Category.cs" />
+    <Compile Include="TaskNote.cs" />
+    <Compile Include="TaskNoteSupport.cs" />
+    <Compile Include="TaskCompletionDateComparer.cs" />
+    <Compile Include="NotifyCollection.cs" />
+    <Compile Include="ReadOnlyNotifyCollection.cs" />
   </ItemGroup>
   <ItemGroup>
     <Reference Include="System" />
diff --git a/src/tasque/Application.cs b/src/tasque/Application.cs
index 8f4ae45..dc319eb 100644
--- a/src/tasque/Application.cs
+++ b/src/tasque/Application.cs
@@ -467,7 +467,7 @@ namespace Tasque
 
 		void RebuildTooltipTaskGroupModels ()
 		{
-			if (backend == null || backend.Tasks == null) {
+			if (backend == null || backend.Tasks2 == null) {
 				overdue_tasks = null;
 				today_tasks = null;
 				tomorrow_tasks = null;
@@ -475,9 +475,9 @@ namespace Tasque
 				return;
 			}
 
-			overdue_tasks = TaskGroupModelFactory.CreateOverdueModel (backend.SortedTasks);
-			today_tasks = TaskGroupModelFactory.CreateTodayModel (backend.SortedTasks);
-			tomorrow_tasks = TaskGroupModelFactory.CreateTomorrowModel (backend.SortedTasks);
+			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 })
 			{
diff --git a/src/tasque/Backends/Dummy/DummyBackend.cs b/src/tasque/Backends/Dummy/DummyBackend.cs
index 88218dc..f0d12dd 100644
--- a/src/tasque/Backends/Dummy/DummyBackend.cs
+++ b/src/tasque/Backends/Dummy/DummyBackend.cs
@@ -27,101 +27,33 @@
 // THE SOFTWARE.
 
 using System;
-using System.Collections;
 using System.Collections.ObjectModel;
-using Tasque.Backends;
 using Tasque.Backends.Dummy.Gtk;
 
 namespace Tasque.Backends.Dummy
 {
 	public class DummyBackend : Backend
 	{
-		/// <summary>
-		/// Keep track of the Gtk.TreeIters for the tasks so that they can
-		/// be referenced later.
-		///
-		/// Key   = Task ID
-		/// Value = Gtk.TreeIter in taskStore
-		/// </summary>
-		int newTaskId;
-		bool initialized;
-		bool configured = true;
-
-		public event BackendInitializedHandler BackendInitialized;
-		public event BackendSyncStartedHandler BackendSyncStarted;
-		public event BackendSyncFinishedHandler BackendSyncFinished;
-		
-		Category homeCategory;
-		Category workCategory;
-		Category projectsCategory;
-		
-		public DummyBackend () : base ()
-		{
-			initialized = false;
-			newTaskId = 0;
-		}
+		public DummyBackend () : base ("Debugging System") {}
 		
 		#region Public Properties
-		public string Name { get { return "Debugging System"; } }
-		
-		/// <value>
-		/// All the tasks including ITaskDivider items.
-		/// </value>
-		public IEnumerable SortedTasks { get; private set; }
-		
-		/// <value>
-		/// This returns all the task lists (categories) that exist.
-		/// </value>
-		public IEnumerable SortedCategories { get; private set; }
-		
-		public ObservableCollection<ICategory> Categories { get; private set; }
-		
 		/// <value>
 		/// Indication that the dummy backend is configured
 		/// </value>
-		public bool Configured { get { return configured; } }
+		public override bool Configured { get { return true; } }
 		
 		/// <value>
 		/// Inidication that the backend is initialized
 		/// </value>
-		public bool Initialized { get { return initialized; } }		
-		#endregion // Public Properties
+		public override bool Initialized { get { return initialized; } }		
+		#endregion
 		
-		#region Public Methods
-		public Task CreateTask (string taskName, ICategory category)
-		{
-			// not sure what to do here with the category
-			DummyTask task = new DummyTask (this, newTaskId, taskName);
-			
-			// Determine and set the task category
-			if (category == null || category is AllCategory)
-				task.Category = workCategory; // Default to work
-			else
-				task.Category = category;
-			
-			tasks.Add (task);
-			newTaskId++;
-			
-			return task;
-		}
-		
-		public void DeleteTask (Task task)
-		{
-		}
+		#region Public Methods		
+		public override void Refresh () {}
 		
-		public void Refresh ()
-		{
-		}
-		
-		public void Initialize ()
+		public override void Initialize ()
 		{
 			//
-			// Add in the "All" Category
-			//
-			AllCategory allCategory = new AllCategory ();
-			Categories.Add (allCategory);
-			
-			//
 			// Add in some fake categories
 			//
 			homeCategory = new Category ("Home");
@@ -136,95 +68,60 @@ namespace Tasque.Backends.Dummy
 			//
 			// Add in some fake tasks
 			//
-			
-			DummyTask task = new DummyTask (this, newTaskId, "Buy some nails");
-			projectsCategory.Add (task);
+			var task = CreateTask ("Buy some nails", projectsCategory);
 			task.DueDate = DateTime.Now.AddDays (1);
 			task.Priority = TaskPriority.Medium;
-			tasks.Add (task);
-			newTaskId++;
 			
-			task = new DummyTask (this, newTaskId, "Call Roger");
-			homeCategory.Add (task);
+			task = CreateTask ("Call Roger", homeCategory);
 			task.DueDate = DateTime.Now.AddDays (-1);
 			task.Complete ();
 			task.CompletionDate = task.DueDate;
-			tasks.Add (task);
-			newTaskId++;
 			
-			task = new DummyTask (this, newTaskId, "Replace burnt out lightbulb");
-			homeCategory.Add (task);
+			task = CreateTask ("Replace burnt out lightbulb", homeCategory);
 			task.DueDate = DateTime.Now;
 			task.Priority = TaskPriority.Low;
-			tasks.Add (task);
-			newTaskId++;
 			
-			task = new DummyTask (this, newTaskId, "File taxes");
-			homeCategory.Add (task);
+			task = CreateTask ("File taxes", homeCategory);
 			task.DueDate = new DateTime (2008, 4, 1);
-			tasks.Add (task);
-			newTaskId++;
 			
-			task = new DummyTask (this, newTaskId, "Purchase lumber");
-			projectsCategory.Add (task);
+			task = CreateTask ("Purchase lumber", projectsCategory);
 			task.DueDate = DateTime.Now.AddDays (1);
 			task.Priority = TaskPriority.High;
-			tasks.Add (task);
-			newTaskId++;
 						
-			task = new DummyTask (this, newTaskId, "Estimate drywall requirements");
-			projectsCategory.Add (task);
+			task = CreateTask ("Estimate drywall requirements", new Category [] { projectsCategory, workCategory });
 			task.DueDate = DateTime.Now.AddDays (1);
 			task.Priority = TaskPriority.Low;
-			tasks.Add (task);
-			newTaskId++;
 			
-			task = new DummyTask (this, newTaskId, "Borrow framing nailer from Ben");
-			projectsCategory.Add (task);
+			task = CreateTask ("Borrow framing nailer from Ben", new Category [] { projectsCategory, homeCategory });
 			task.DueDate = DateTime.Now.AddDays (1);
 			task.Priority = TaskPriority.High;
-			tasks.Add (task);
-			newTaskId++;
 			
-			task = new DummyTask (this, newTaskId, "Call for an insulation estimate");
-			projectsCategory.Add (task);
+			task = CreateTask ("Call for an insulation estimate", projectsCategory);
 			task.DueDate = DateTime.Now.AddDays (1);
 			task.Priority = TaskPriority.Medium;
-			tasks.Add (task);
-			newTaskId++;
 			
-			task = new DummyTask (this, newTaskId, "Pay storage rental fee");
-			homeCategory.Add (task);
+			task = CreateTask ("Pay storage rental fee", homeCategory);
 			task.DueDate = DateTime.Now.AddDays (1);
 			task.Priority = TaskPriority.None;
-			tasks.Add (task);
-			newTaskId++;
 			
-			task = new DummyTask (this, newTaskId, "Place carpet order");
+			task = new DummyTask ("Place carpet order");
 			projectsCategory.Add (task);
 			task.Priority = TaskPriority.None;
-			tasks.Add (task);
-			newTaskId++;
 			
-			task = new DummyTask (this, newTaskId, "Test task overdue");
+			task = new DummyTask ("Test task overdue");
 			workCategory.Add (task);
+			projectsCategory.Add (task);
 			task.DueDate = DateTime.Now.AddDays (-89);
 			task.Priority = TaskPriority.None;
 			task.Complete ();
-			tasks.Add (task);
-			newTaskId++;
 			
 			initialized = true;
-			if (BackendInitialized != null) {
-				BackendInitialized ();
-			}		
+			OnBackendInitialized ();
 		}
 
-		public void Cleanup ()
-		{
-		}
+		public override void Cleanup () {}
 		
-		public IBackendPreferences Preferences
+		public override IBackendPreferences Preferences
 		{
 			get {
 				// TODO: Replace this with returning null once things are going
@@ -232,8 +129,19 @@ namespace Tasque.Backends.Dummy
 				return new DummyPreferences ();
 			}
 		}
-		#endregion // Public Methods
-		
+		#endregion
+
+		protected override Task CreateTaskCore (string taskName)
+		{
+			return new DummyTask (taskName);
+		}
+
+		bool initialized;
+
 		ObservableCollection<Task> tasks;
+
+		Category homeCategory;
+		Category projectsCategory;
+		Category workCategory;
 	}
 }
diff --git a/src/tasque/Backends/Dummy/DummyNote.cs b/src/tasque/Backends/Dummy/DummyNote.cs
index f5e727b..52a8d4b 100644
--- a/src/tasque/Backends/Dummy/DummyNote.cs
+++ b/src/tasque/Backends/Dummy/DummyNote.cs
@@ -3,27 +3,37 @@
 //
 // To change standard headers go to Edit->Preferences->Coding->Standard Headers
 //
-
-using System;
+// 
+// DummyNote.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 Tasque;
 
 namespace Tasque.Backends.Dummy
 {
-	public class DummyNote : INote
+	public class DummyNote : TaskNote
 	{
-		public string Name
-		{
-			get { return ""; }
-			set { // TODO: Implement something 
-			}
-		}
-   
-		public string Text
-		{
-			get { return ""; }
-			set { // TODO: Implement something 
-			}
-		}
-
+		public override string Text { get; set; }
 	}
 }
\ No newline at end of file
diff --git a/src/tasque/Backends/Dummy/DummyTask.cs b/src/tasque/Backends/Dummy/DummyTask.cs
index 6b7578e..ead14a9 100644
--- a/src/tasque/Backends/Dummy/DummyTask.cs
+++ b/src/tasque/Backends/Dummy/DummyTask.cs
@@ -1,53 +1,58 @@
 // DummyTask.cs created with MonoDevelop
 // User: boyd at 8:50 PMÂ2/10/2008
-
+// 
+// DummyTask.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 Tasque;
 using System.Collections.Generic;
+using Tasque;
+using System.Collections.ObjectModel;
 
 namespace Tasque.Backends.Dummy
 {
-	public class DummyTask : AbstractTask
+	public class DummyTask : Task
 	{
-		string name;
-		DateTime dueDate;
-		DateTime completionDate;
-		TaskPriority priority;
-		TaskState state;
-		int id;
-		
-		public DummyTask(DummyBackend backend, int id, string taskName) : base (backend)
+		public DummyTask(string name) : base (name)
 		{
-			this.id = id;
-			this.name = taskName;
-			this.dueDate = DateTime.MinValue; // No due date specified
-			this.completionDate = DateTime.MinValue; // No due date specified
-			this.priority = TaskPriority.None;
-			this.state = TaskState.Active;
+			notes = new ObservableCollection<TaskNote> ();
+			Notes = new ReadOnlyObservableCollection<TaskNote> (notes);
 		}
 		
 		#region Public Properties
-
-		public override string Id
-		{
-			get { return id.ToString(); }
-		}
-		
-		public override string Name
+		public override DateTime CompletionDate
 		{
-			get { return name; }
+			get { return completionDate; }
 			set {
-				if (value != name) {
-					Logger.Debug ("Setting new task name");
-					if (value == null)
-						name = string.Empty;
-				
-					name = value.Trim ();
-					OnPropertyChanged ("Name");
+				if (value != completionDate) {
+					Logger.Debug ("Setting new task completion date");
+					completionDate = value;
+					OnPropertyChanged ("CompletionDate");
 				}
 			}
 		}
-		
+
 		public override DateTime DueDate
 		{
 			get { return dueDate; }
@@ -59,24 +64,9 @@ namespace Tasque.Backends.Dummy
 				}
 			}
 		}
-		
-		public override DateTime CompletionDate
-		{
-			get { return completionDate; }
-			set {
-				if (value != completionDate) {
-					Logger.Debug ("Setting new task completion date");
-					completionDate = value;
-					OnPropertyChanged ("CompletionDate");
-				}
-			}
-		}
-		
-		public override bool IsComplete
-		{
-			get { return state == TaskState.Completed; }
-		}
-		
+
+		public override ReadOnlyObservableCollection<TaskNote> Notes { get; private set; }
+
 		public override TaskPriority Priority
 		{
 			get { return priority; }
@@ -89,73 +79,63 @@ namespace Tasque.Backends.Dummy
 			}
 		}
 
-		public override bool HasNotes
-		{
-			get { return true; }
-		}
-		
-		public override bool SupportsMultipleNotes
-		{
-			get { return true; }
-		}
-		
-		public override TaskState State
-		{
+		public override TaskState State {
 			get { return state; }
+			set {
+				if (state != value) {
+					state = value;
+					OnPropertyChanged ("State");
+				}
+			}
 		}
-		
-		public override List<INote> Notes
-		{
-			get { return null; }
-		}		
-		
-		#endregion // Public Properties
+
+		public override TaskNoteSupport TaskNoteSupport { get { return TaskNoteSupport.Multiple; } }
+		#endregion
 		
 		#region Public Methods
 		public override void Activate ()
 		{
 			Logger.Debug ("DummyTask.Activate ()");
 			completionDate = DateTime.MinValue;
-			state = TaskState.Active;
-			OnPropertyChanged ("State");
-		}
-		
-		public override void Inactivate ()
-		{
-			Logger.Debug ("DummyTask.Inactivate ()");
-			completionDate = DateTime.Now;
-			state = TaskState.Inactive;
-			OnPropertyChanged ("State");
+			State = TaskState.Active;
 		}
 		
 		public override void Complete ()
 		{
 			Logger.Debug ("DummyTask.Complete ()");
 			CompletionDate = DateTime.Now;
-			state = TaskState.Completed;
-			OnPropertyChanged ("State");
+			State = TaskState.Completed;
 		}
 		
 		public override void Delete ()
 		{
 			Logger.Debug ("DummyTask.Delete ()");
-			state = TaskState.Deleted;
-			OnPropertyChanged ("State");
+			State = TaskState.Deleted;
 		}
 		
-		public override INote CreateNote(string text)
+		public override TaskNote CreateNote(string text)
 		{
-			return null;
+			if (text == null)
+				throw new ArgumentNullException ("text");
+
+			var note = new TaskNote (text);
+			notes.Add (note);
+			return note;
 		}
 		
-		public override void DeleteNote(INote note)
+		public override void DeleteNote(TaskNote note)
 		{
 		}
 
-		public override void SaveNote(INote note)
+		public override void SaveNote(TaskNote note)
 		{
 		}
+		#endregion
 
-		#endregion // Public Methods
+		DateTime completionDate;
+		DateTime dueDate;
+		ObservableCollection<TaskNote> notes;
+		TaskPriority priority;
+		TaskState state;
 	}
 }
diff --git a/src/tasque/Backends/Hiveminder/HmBackend.cs b/src/tasque/Backends/Hiveminder/HmBackend.cs
index 2b494a2..958c2bc 100644
--- a/src/tasque/Backends/Hiveminder/HmBackend.cs
+++ b/src/tasque/Backends/Hiveminder/HmBackend.cs
@@ -86,7 +86,7 @@ namespace Tasque.Backends.HmBackend
 			sortedTasksModel.SetSortFunc (0, new Gtk.TreeIterCompareFunc (CompareTasksSortFunc));
 			sortedTasksModel.SetSortColumnId (0, Gtk.SortType.Ascending);
 			
-			categoryListStore = new Gtk.ListStore (typeof (ICategory));
+			categoryListStore = new Gtk.ListStore (typeof (Category));
 			
 			sortedCategoriesModel = new Gtk.TreeModelSort (categoryListStore);
 			sortedCategoriesModel.SetSortFunc (0, new Gtk.TreeIterCompareFunc (CompareCategorySortFunc));
@@ -144,7 +144,7 @@ namespace Tasque.Backends.HmBackend
 		#endregion // Public Properties
 		
 		#region Public Methods
-		public Task CreateTask (string taskName, ICategory category)		
+		public Task CreateTask (string taskName, Category category)		
 		{
 			Hiveminder.Task task = new Task ();
 			Hiveminder.Task createdTask;
@@ -318,8 +318,8 @@ namespace Tasque.Backends.HmBackend
 											Gtk.TreeIter a,
 											Gtk.TreeIter b)
 		{
-			ICategory categoryA = model.GetValue (a, 0) as ICategory;
-			ICategory categoryB = model.GetValue (b, 0) as ICategory;
+			Category categoryA = model.GetValue (a, 0) as Category;
+			Category categoryB = model.GetValue (b, 0) as Category;
 			
 			if (categoryA == null || categoryB == null)
 				return 0;
diff --git a/src/tasque/Backends/Hiveminder/HmCategory.cs b/src/tasque/Backends/Hiveminder/HmCategory.cs
index 6bc1877..93f745b 100644
--- a/src/tasque/Backends/Hiveminder/HmCategory.cs
+++ b/src/tasque/Backends/Hiveminder/HmCategory.cs
@@ -34,7 +34,7 @@ using Hiveminder;
 
 namespace Tasque.Backends.HmBackend
 {
-	public class HmCategory : ICategory
+	public class HmCategory : Category
 	{
 		Group group;
 		
diff --git a/src/tasque/Backends/Hiveminder/HmNote.cs b/src/tasque/Backends/Hiveminder/HmNote.cs
index be3666d..dae909a 100644
--- a/src/tasque/Backends/Hiveminder/HmNote.cs
+++ b/src/tasque/Backends/Hiveminder/HmNote.cs
@@ -27,7 +27,7 @@ using Tasque;
 
 namespace Tasque.Backends.HmBackend
 {
-       public class HmNote : INote
+       public class HmNote : TaskNote
        {
 	       private Hiveminder.Task task;
 
diff --git a/src/tasque/Backends/Hiveminder/HmTask.cs b/src/tasque/Backends/Hiveminder/HmTask.cs
index fa58e06..4d592ea 100644
--- a/src/tasque/Backends/Hiveminder/HmTask.cs
+++ b/src/tasque/Backends/Hiveminder/HmTask.cs
@@ -39,7 +39,7 @@ namespace Tasque.Backends.HmBackend
 		Task task;
 
 		private HmBackend backend;
-		private List <INote> notes;
+		private List <TaskNote> notes;
 		
 		#region Properties
 		
@@ -136,13 +136,13 @@ namespace Tasque.Backends.HmBackend
 			}
 		}
 		
-		public override ICategory Category
+		public override Category Category
 		{
 			get {return null;} 
 			set { Logger.Info ("Not implemented");}
 		}
 		
-		public override List<INote> Notes
+		public override List<TaskNote> Notes
 		{
 			get {
 				return this.notes; 
@@ -197,7 +197,7 @@ namespace Tasque.Backends.HmBackend
 			this.backend = hmBackend;
 
 			//Add Description as note.
-			this.notes = new List<INote>();
+			this.notes = new List<TaskNote>();
 
 			if (!string.IsNullOrEmpty (this.task.Description)) 
 				notes.Add (new HmNote (this.task));
@@ -245,7 +245,7 @@ namespace Tasque.Backends.HmBackend
 		/// <param name="note">
 		/// A <see cref="INote"/>
 		/// </param>
-		public override INote CreateNote(string text)
+		public override TaskNote CreateNote(string text)
 		{
 			Logger.Debug ("CreateNote : " + text);
 
@@ -266,7 +266,7 @@ namespace Tasque.Backends.HmBackend
 		/// <param name="note">
 		/// A <see cref="INote"/>
 		/// </param>
-		public override void DeleteNote(INote note)
+		public override void DeleteNote(TaskNote note)
 		{
 		       Logger.Debug ("DeleteNote : " + note.Text);
 
@@ -287,7 +287,7 @@ namespace Tasque.Backends.HmBackend
 		/// <param name="note">
 		/// A <see cref="INote"/>
 		/// </param>
-		public override void SaveNote(INote note)
+		public override void SaveNote(TaskNote note)
 		{		
 			Logger.Debug ("SaveNote : " + note.Text);
 
diff --git a/src/tasque/Backends/Rtm/RtmBackend.cs b/src/tasque/Backends/Rtm/RtmBackend.cs
index 3781249..881b77f 100644
--- a/src/tasque/Backends/Rtm/RtmBackend.cs
+++ b/src/tasque/Backends/Rtm/RtmBackend.cs
@@ -58,7 +58,7 @@ namespace Tasque.Backends.RtmBackend
 			// *************************************
 			Tasks = new ObservableCollection<Task>();
 
-			categoryListStore = new Gtk.ListStore (typeof (ICategory));
+			categoryListStore = new Gtk.ListStore (typeof (Category));
 
 			sortedCategoriesModel = new Gtk.TreeModelSort (categoryListStore);
 			sortedCategoriesModel.SetSortFunc (0, new Gtk.TreeIterCompareFunc (CompareCategorySortFunc));
@@ -86,7 +86,7 @@ namespace Tasque.Backends.RtmBackend
 		/// <value>
 		/// All the tasks including ITaskDivider items.
 		/// </value>
-		public IEnumerable<Task> SortedTasks
+		public IEnumerable<Task> Tasks
 		{
 			get { return Tasks.OrderBy (t => t, Comparer<Task>.Default); }
 		}
@@ -96,7 +96,7 @@ namespace Tasque.Backends.RtmBackend
 		/// <value>
 		/// This returns all the task lists (categories) that exist.
 		/// </value>
-		public Gtk.TreeModel Categories
+		public Gtk.TreeModel Categories2
 		{
 			get { return sortedCategoriesModel; }
 		}
@@ -130,7 +130,7 @@ namespace Tasque.Backends.RtmBackend
 #endregion // Public Properties
 
 #region Public Methods
-		public Task CreateTask (string taskName, ICategory category)
+		public Task CreateTask (string taskName, Category category)
 		{
 			string categoryID;
 			RtmTask rtmTask = null;
@@ -518,8 +518,8 @@ namespace Tasque.Backends.RtmBackend
 											Gtk.TreeIter a,
 											Gtk.TreeIter b)
 		{
-			ICategory categoryA = model.GetValue (a, 0) as ICategory;
-			ICategory categoryB = model.GetValue (b, 0) as ICategory;
+			Category categoryA = model.GetValue (a, 0) as Category;
+			Category categoryB = model.GetValue (b, 0) as Category;
 			
 			if (categoryA == null || categoryB == null)
 				return 0;
diff --git a/src/tasque/Backends/Rtm/RtmCategory.cs b/src/tasque/Backends/Rtm/RtmCategory.cs
index 751212b..5d1ce81 100644
--- a/src/tasque/Backends/Rtm/RtmCategory.cs
+++ b/src/tasque/Backends/Rtm/RtmCategory.cs
@@ -10,7 +10,7 @@ using RtmNet;
 
 namespace Tasque.Backends.RtmBackend
 {
-	public class RtmCategory : ICategory
+	public class RtmCategory : Category
 	{
 		private List list;
 		private Gtk.TreeIter iter;
diff --git a/src/tasque/Backends/Rtm/RtmNote.cs b/src/tasque/Backends/Rtm/RtmNote.cs
index 72b0689..c058bae 100644
--- a/src/tasque/Backends/Rtm/RtmNote.cs
+++ b/src/tasque/Backends/Rtm/RtmNote.cs
@@ -10,7 +10,7 @@ using RtmNet;
 
 namespace Tasque.Backends.RtmBackend
 {
-	public class RtmNote : INote
+	public class RtmNote : TaskNote
 	{
 		Note note;
 		
diff --git a/src/tasque/Backends/Rtm/RtmTask.cs b/src/tasque/Backends/Rtm/RtmTask.cs
index ff7c3e6..27bc03f 100644
--- a/src/tasque/Backends/Rtm/RtmTask.cs
+++ b/src/tasque/Backends/Rtm/RtmTask.cs
@@ -12,7 +12,7 @@ namespace Tasque.Backends.RtmBackend
 		private RtmBackend rtmBackend;
 		private TaskState state;
 		private RtmCategory category;
-		private List<INote> notes;		
+		private List<TaskNote> notes;		
 		
 		TaskSeries taskSeries;
 		
@@ -32,7 +32,7 @@ namespace Tasque.Backends.RtmBackend
 				state = TaskState.Active;
 			else
 				state = TaskState.Completed;
-			notes = new List<INote>();
+			notes = new List<TaskNote>();
 
 			if (taskSeries.Notes.NoteCollection != null) {
 				foreach(Note note in taskSeries.Notes.NoteCollection) {
@@ -183,7 +183,7 @@ namespace Tasque.Backends.RtmBackend
 		/// <value>
 		/// Returns the category object for this task
 		/// </value>
-		public override ICategory Category
+		public override Category Category
 		{
 			get { return category; } 
 			set {
@@ -195,7 +195,7 @@ namespace Tasque.Backends.RtmBackend
 		/// <value>
 		/// Returns the notes associates with this task
 		/// </value>
-		public override List<INote> Notes
+		public override List<TaskNote> Notes
 		{
 			get { return notes; }
 		}
@@ -279,7 +279,7 @@ namespace Tasque.Backends.RtmBackend
 		/// <param name="note">
 		/// A <see cref="INote"/>
 		/// </param>
-		public override INote CreateNote(string text)
+		public override TaskNote CreateNote(string text)
 		{
 			RtmNote rtmNote;
 			
@@ -295,7 +295,7 @@ namespace Tasque.Backends.RtmBackend
 		/// <param name="note">
 		/// A <see cref="INote"/>
 		/// </param>
-		public override void DeleteNote(INote note)
+		public override void DeleteNote(TaskNote note)
 		{
 			RtmNote rtmNote = (note as RtmNote);
 			
@@ -314,7 +314,7 @@ namespace Tasque.Backends.RtmBackend
 		/// <param name="note">
 		/// A <see cref="INote"/>
 		/// </param>
-		public override void SaveNote(INote note)
+		public override void SaveNote(TaskNote note)
 		{		
 			rtmBackend.SaveNote(this, (note as RtmNote));
 		}		
diff --git a/src/tasque/Backends/Sqlite/SqliteBackend.cs b/src/tasque/Backends/Sqlite/SqliteBackend.cs
index 12dd985..7f1a831 100644
--- a/src/tasque/Backends/Sqlite/SqliteBackend.cs
+++ b/src/tasque/Backends/Sqlite/SqliteBackend.cs
@@ -40,7 +40,7 @@ namespace Tasque.Backends.Sqlite
 			sortedTasksModel.SetSortFunc (0, new Gtk.TreeIterCompareFunc (CompareTasksSortFunc));
 			sortedTasksModel.SetSortColumnId (0, Gtk.SortType.Ascending);
 			
-			categoryListStore = new Gtk.ListStore (typeof (ICategory));
+			categoryListStore = new Gtk.ListStore (typeof (Category));
 			
 			sortedCategoriesModel = new Gtk.TreeModelSort (categoryListStore);
 			sortedCategoriesModel.SetSortFunc (0, new Gtk.TreeIterCompareFunc (CompareCategorySortFunc));
@@ -93,7 +93,7 @@ namespace Tasque.Backends.Sqlite
 		#endregion // Public Properties
 		
 		#region Public Methods
-		public Task CreateTask (string taskName, ICategory category)		
+		public Task CreateTask (string taskName, Category category)		
 		{
 			// not sure what to do here with the category
 			SqliteTask task = new SqliteTask (this, taskName);
@@ -196,8 +196,8 @@ namespace Tasque.Backends.Sqlite
 											Gtk.TreeIter a,
 											Gtk.TreeIter b)
 		{
-			ICategory categoryA = model.GetValue (a, 0) as ICategory;
-			ICategory categoryB = model.GetValue (b, 0) as ICategory;
+			Category categoryA = model.GetValue (a, 0) as Category;
+			Category categoryB = model.GetValue (b, 0) as Category;
 			
 			if (categoryA == null || categoryB == null)
 				return 0;
diff --git a/src/tasque/Backends/Sqlite/SqliteCategory.cs b/src/tasque/Backends/Sqlite/SqliteCategory.cs
index 3605cc0..146c077 100644
--- a/src/tasque/Backends/Sqlite/SqliteCategory.cs
+++ b/src/tasque/Backends/Sqlite/SqliteCategory.cs
@@ -9,7 +9,7 @@ using Tasque;
 
 namespace Tasque.Backends.Sqlite
 {
-	public class SqliteCategory : ICategory
+	public class SqliteCategory : Category
 	{
 		private int id;
 		SqliteBackend backend;
diff --git a/src/tasque/Backends/Sqlite/SqliteNote.cs b/src/tasque/Backends/Sqlite/SqliteNote.cs
index 733b780..3875a9d 100644
--- a/src/tasque/Backends/Sqlite/SqliteNote.cs
+++ b/src/tasque/Backends/Sqlite/SqliteNote.cs
@@ -9,7 +9,7 @@ using Tasque;
 
 namespace Tasque.Backends.Sqlite
 {
-	public class SqliteNote : INote
+	public class SqliteNote : TaskNote
 	{
 		private int id;
 		private string text;
diff --git a/src/tasque/Backends/Sqlite/SqliteTask.cs b/src/tasque/Backends/Sqlite/SqliteTask.cs
index 9ede1b1..3f817ea 100644
--- a/src/tasque/Backends/Sqlite/SqliteTask.cs
+++ b/src/tasque/Backends/Sqlite/SqliteTask.cs
@@ -147,7 +147,7 @@ namespace Tasque.Backends.Sqlite
 			}
 		}
 
-		public override ICategory Category
+		public override Category Category
 		{
 			get { return new SqliteCategory(backend, this.category); }
 			set {
@@ -158,10 +158,10 @@ namespace Tasque.Backends.Sqlite
 			}
 		}
 		
-		public override List<INote> Notes
+		public override List<TaskNote> Notes
 		{
 			get {
-				List<INote> notes = new List<INote>();
+				List<TaskNote> notes = new List<TaskNote>();
 
 				string command = String.Format("SELECT ID, Text FROM Notes WHERE Task='{0}'", id);
 				SqliteCommand cmd = backend.Database.Connection.CreateCommand();
@@ -211,7 +211,7 @@ namespace Tasque.Backends.Sqlite
 			backend.UpdateTask (this);
 		}
 		
-		public override INote CreateNote(string text)
+		public override TaskNote CreateNote(string text)
 		{
 			Logger.Debug("Creating New Note Object : {0} (id={1})", text, id);
 			text = backend.SanitizeText (text);
@@ -221,7 +221,7 @@ namespace Tasque.Backends.Sqlite
 			return new SqliteNote (taskId, text);
 		}
 		
-		public override void DeleteNote(INote note)
+		public override void DeleteNote(TaskNote note)
 		{
 			SqliteNote sqNote = (note as SqliteNote);
 
@@ -229,7 +229,7 @@ namespace Tasque.Backends.Sqlite
 			backend.Database.ExecuteScalar(command);
 		}
 
-		public override void SaveNote(INote note)
+		public override void SaveNote(TaskNote note)
 		{
 			SqliteNote sqNote = (note as SqliteNote);
 
diff --git a/src/tasque/CompletedTaskGroup.cs b/src/tasque/CompletedTaskGroup.cs
index f5762c1..c917f75 100644
--- a/src/tasque/CompletedTaskGroup.cs
+++ b/src/tasque/CompletedTaskGroup.cs
@@ -39,7 +39,7 @@ namespace Tasque
 			return cv;
 		}
 		
-		ICategory selectedCategory;
+		Category selectedCategory;
 		HScale rangeSlider;
 		ShowCompletedRange currentRange;
 		
@@ -110,13 +110,13 @@ namespace Tasque
 			Refilter (selectedCategory);
 		}
 		
-		protected ICategory GetSelectedCategory ()
+		protected Category GetSelectedCategory ()
 		{
-			ICategory foundCategory = null;
+			Category foundCategory = null;
 			
 			string cat = Application.Preferences.Get (Preferences.SelectedCategoryKey);
 			if (cat != null) {
-				var categories = Application.Backend.Categories;
+				var categories = Application.Backend.Categories2;
 				foundCategory = categories.SingleOrDefault (c => c.Name == cat);
 			}
 			
diff --git a/src/tasque/NoteDialog.cs b/src/tasque/NoteDialog.cs
index 2c3a636..7392ece 100644
--- a/src/tasque/NoteDialog.cs
+++ b/src/tasque/NoteDialog.cs
@@ -46,7 +46,7 @@ namespace Tasque
 			innerEb.Show ();
 			
 			if(task.Notes != null) {
-				foreach (INote note in task.Notes) {
+				foreach (TaskNote note in task.Notes) {
 					NoteWidget noteWidget = new NoteWidget (note);
 					noteWidget.TextChanged += OnNoteTextChanged;
 					noteWidget.DeleteButtonClicked += OnDeleteButtonClicked;
@@ -140,7 +140,7 @@ namespace Tasque
 			// if null, add a note, else, modify it
 			if(nWidget.Note == null) {
 				try {
-					INote note = task.CreateNote(nWidget.Text);
+					TaskNote note = task.CreateNote(nWidget.Text);
 					nWidget.Note = note;
 				} catch(Exception e) {
 					Logger.Debug("Unable to create a note");
diff --git a/src/tasque/NoteWidget.cs b/src/tasque/NoteWidget.cs
index 7c1a32f..f454f3f 100644
--- a/src/tasque/NoteWidget.cs
+++ b/src/tasque/NoteWidget.cs
@@ -9,7 +9,7 @@ namespace Tasque
 {
 	public class NoteWidget : Gtk.Notebook
 	{
-		private INote note;
+		private TaskNote note;
 		private string text;
 		
 		private Gtk.Widget viewPage;
@@ -33,7 +33,7 @@ namespace Tasque
 		private Gtk.Button saveButton;
 				
 		#region Constructors
-		public NoteWidget (INote note)
+		public NoteWidget (TaskNote note)
 		{
 			this.KeyPressEvent += OnNoteWidgetKeyPressed;
 			this.note = note;
@@ -71,7 +71,7 @@ namespace Tasque
 		#endregion // Events
 		
 		#region Properties
-		public INote Note
+		public TaskNote Note
 		{
 			get { return note; }
 			set { 
diff --git a/src/tasque/PreferencesDialog.cs b/src/tasque/PreferencesDialog.cs
index bbf5e69..0b7651b 100644
--- a/src/tasque/PreferencesDialog.cs
+++ b/src/tasque/PreferencesDialog.cs
@@ -51,7 +51,7 @@ namespace Tasque
 		Dictionary<int, Backend> backendComboMap; // track backends
 		int 					selectedBackend;
 		Gtk.CheckButton			showCompletedTasksCheckButton;
-		CollectionView<ICategory> filteredCategories;
+		CollectionView<Category> filteredCategories;
 		List<string>			categoriesToHide;
 		Gtk.TreeView			categoriesTree;
 
@@ -494,7 +494,7 @@ namespace Tasque
 											 Gtk.TreeIter iter)
 		{
 			Gtk.CellRendererToggle crt = cell as Gtk.CellRendererToggle;
-			ICategory category = model.GetValue (iter, 0) as ICategory;
+			Category category = model.GetValue (iter, 0) as Category;
 			if (category == null) {
 				crt.Active = true;
 				return;
@@ -521,7 +521,7 @@ namespace Tasque
 		{
 			Gtk.CellRendererText crt = renderer as Gtk.CellRendererText;
 			crt.Ellipsize = Pango.EllipsizeMode.End;
-			ICategory category = model.GetValue (iter, 0) as ICategory;
+			Category category = model.GetValue (iter, 0) as Category;
 			if (category == null) {
 				crt.Text = string.Empty;
 				return;
@@ -538,7 +538,7 @@ namespace Tasque
 			if (!categoriesTree.Model.GetIter (out iter, path))
 				return; // Do nothing
 			
-			ICategory category = categoriesTree.Model.GetValue (iter, 0) as ICategory;
+			Category category = categoriesTree.Model.GetValue (iter, 0) as Category;
 			if (category == null)
 				return;
 			
@@ -594,10 +594,10 @@ namespace Tasque
 			}
 			
 			Backend backend = backendComboMap [selectedBackend];
-			filteredCategories = new CollectionView<ICategory> (backend.SortedCategories);
+			filteredCategories = new CollectionView<Category> (backend.Categories);
 			// Filter out the AllCategory
 			filteredCategories.Filter = c => c != null && !(c is AllCategory);
-			var adapter = new TreeModelListAdapter<ICategory> (filteredCategories);
+			var adapter = new TreeModelListAdapter<Category> (filteredCategories);
 			categoriesTree.Model = adapter;
 		}
 		
diff --git a/src/tasque/RemoteControl.cs b/src/tasque/RemoteControl.cs
index 76c4960..072ff57 100644
--- a/src/tasque/RemoteControl.cs
+++ b/src/tasque/RemoteControl.cs
@@ -85,7 +85,7 @@ namespace Tasque
 		public string CreateTask (string categoryName, string taskName,
 						bool enterEditMode, bool parseDate)
 		{
-			var categories = Application.Backend.Categories;
+			var categories = Application.Backend.Categories2;
 			
 			//
 			// Validate the input parameters.  Don't allow null or empty strings
@@ -97,7 +97,7 @@ namespace Tasque
 			//
 			// Look for the specified category
 			//
-			ICategory category = null;
+			Category category = null;
 			categories.SingleOrDefault (c => c.Name.ToLower () == categoryName.ToLower ());
 			
 			if (category == null)
@@ -153,13 +153,13 @@ namespace Tasque
 		public string[] GetCategoryNames ()
 		{
 			List<string> categories = new List<string> ();
-			var model = Application.Backend.SortedCategories;
+			var model = Application.Backend.Categories;
 			
 			foreach (var item in model) {
 				if (item is AllCategory)
 					continue;
 				
-				categories.Add (((ICategory)item).Name);
+				categories.Add (((Category)item).Name);
 			}
 			
 			return categories.ToArray ();
@@ -179,7 +179,7 @@ namespace Tasque
 		/// </returns>
 		public string[] GetTaskIds ()
 		{
-			var model = Application.Backend.Tasks;
+			var model = Application.Backend.Tasks2;
 
 			if (model == null)
 				return new string[0];
@@ -266,7 +266,7 @@ namespace Tasque
 			if (task == null)
 				return false;
 			
-			var categories = Application.Backend.Categories;
+			var categories = Application.Backend.Categories2;
 			return categories.Contains (task.Category);
 		}
 		
@@ -443,7 +443,7 @@ namespace Tasque
 		/// </returns>
 		private Task GetTaskById (string id)
 		{
-			return Application.Backend.Tasks.SingleOrDefault (f => f.Id == id);
+			return Application.Backend.Tasks2.SingleOrDefault (f => f.Id == id);
 		}
 	}
 }
diff --git a/src/tasque/TaskGroup.cs b/src/tasque/TaskGroup.cs
index 3206a95..7432a89 100644
--- a/src/tasque/TaskGroup.cs
+++ b/src/tasque/TaskGroup.cs
@@ -209,7 +209,7 @@ namespace Tasque
 		#endregion // Public Properties
 		
 		#region Public Methods
-		public void Refilter (ICategory selectedCategory)
+		public void Refilter (Category selectedCategory)
 		{
 			filteredTasks.Refresh ();
 			treeView.Refilter (selectedCategory);
@@ -363,7 +363,7 @@ namespace Tasque
 		/// </summary>
 		private void Refilter ()
 		{
-			ICategory cat = GetSelectedCategory ();
+			Category cat = GetSelectedCategory ();
 			if (cat != null)
 				Refilter (cat);
 		}
@@ -376,7 +376,7 @@ namespace Tasque
 		/// <returns>
 		/// A <see cref="ICategory"/>
 		/// </returns>
-		ICategory GetSelectedCategory ()
+		Category GetSelectedCategory ()
 		{
 			// TODO: Move this code into some function in the backend/somewhere
 			// with the signature of GetCategoryForName (string catName):ICategory
@@ -384,7 +384,7 @@ namespace Tasque
 				Application.Preferences.Get (Preferences.SelectedCategoryKey);
 			
 			if (selectedCategoryName != null) {
-				var categories = Application.Backend.Categories;
+				var categories = Application.Backend.Categories2;
 				return categories.SingleOrDefault (c => c.Name == selectedCategoryName);
 			}
 			
@@ -456,7 +456,7 @@ namespace Tasque
 			
 			filteredTasks.ShowCompletedTasks = newValue;
 			
-			ICategory cat = GetSelectedCategory ();
+			Category cat = GetSelectedCategory ();
 			if (cat != null)
 				Refilter (cat);
 		}
diff --git a/src/tasque/TaskTreeView.cs b/src/tasque/TaskTreeView.cs
index a427f1b..eb74e46 100644
--- a/src/tasque/TaskTreeView.cs
+++ b/src/tasque/TaskTreeView.cs
@@ -19,7 +19,7 @@ namespace Tasque
 		private static Gdk.Pixbuf[] inactiveAnimPixbufs;
 		
 		private Gtk.TreeModelFilter modelFilter;
-		private ICategory filterCategory;	
+		private Category filterCategory;	
 		private Task taskBeingEdited = null;
 		private bool toggled;
 
@@ -300,7 +300,7 @@ namespace Tasque
 			Refilter (filterCategory);
 		}
 		
-		public void Refilter (ICategory selectedCategory)
+		public void Refilter (Category selectedCategory)
 		{
 			this.filterCategory = selectedCategory;
 			Model = modelFilter;
diff --git a/src/tasque/TaskWindow.cs b/src/tasque/TaskWindow.cs
index 3d6bbaf..65ead96 100644
--- a/src/tasque/TaskWindow.cs
+++ b/src/tasque/TaskWindow.cs
@@ -258,7 +258,7 @@ namespace Tasque
 			
 			overdueGroup = new TaskGroup (Catalog.GetString ("Overdue"),
 										  rangeStart, rangeEnd,
-										  backend.SortedTasks);
+										  backend.Tasks);
 			overdueGroup.RowActivated += OnRowActivated;
 			overdueGroup.ButtonPressed += OnButtonPressed;
 			overdueGroup.Show ();
@@ -276,7 +276,7 @@ namespace Tasque
 									 rangeEnd.Day, 23, 59, 59);
 			todayGroup = new TaskGroup (Catalog.GetString ("Today"),
 										rangeStart, rangeEnd,
-										backend.SortedTasks);
+										backend.Tasks);
 			todayGroup.RowActivated += OnRowActivated;
 			todayGroup.ButtonPressed += OnButtonPressed;
 			todayGroup.Show ();
@@ -294,7 +294,7 @@ namespace Tasque
 									 rangeEnd.Day, 23, 59, 59);
 			tomorrowGroup = new TaskGroup (Catalog.GetString ("Tomorrow"),
 										   rangeStart, rangeEnd,
-										   backend.SortedTasks);
+										   backend.Tasks);
 			tomorrowGroup.RowActivated += OnRowActivated;
 			tomorrowGroup.ButtonPressed += OnButtonPressed;			
 			tomorrowGroup.Show ();
@@ -312,7 +312,7 @@ namespace Tasque
 									 rangeEnd.Day, 23, 59, 59);
 			nextSevenDaysGroup = new TaskGroup (Catalog.GetString ("Next 7 Days"),
 										   rangeStart, rangeEnd,
-										   backend.SortedTasks);
+										   backend.Tasks);
 			nextSevenDaysGroup.RowActivated += OnRowActivated;
 			nextSevenDaysGroup.ButtonPressed += OnButtonPressed;				
 			nextSevenDaysGroup.Show ();
@@ -328,7 +328,7 @@ namespace Tasque
 			rangeEnd = DateTime.MaxValue;
 			futureGroup = new TaskGroup (Catalog.GetString ("Future"),
 										 rangeStart, rangeEnd,
-										 backend.SortedTasks);
+										 backend.Tasks);
 			futureGroup.RowActivated += OnRowActivated;
 			futureGroup.ButtonPressed += OnButtonPressed;			
 			futureGroup.Show ();
@@ -343,7 +343,7 @@ namespace Tasque
 			completedTaskGroup = new CompletedTaskGroup (
 					Catalog.GetString ("Completed"),
 					rangeStart, rangeEnd,
-					backend.SortedTasks);
+					backend.Tasks);
 			completedTaskGroup.RowActivated += OnRowActivated;
 			completedTaskGroup.ButtonPressed += OnButtonPressed;
 			completedTaskGroup.Show ();
@@ -358,7 +358,7 @@ namespace Tasque
 			
 			// Set up the combo box (after the above to set the current filter)
 
-			var adapter = new TreeModelListAdapter<ICategory> (Application.Backend.SortedCategories);
+			var adapter = new TreeModelListAdapter<Category> (Application.Backend.Categories);
 			categoryComboBox.Model = adapter;	
 
 			// Read preferences for the last-selected category and select it
@@ -640,7 +640,7 @@ namespace Tasque
 									   Gtk.TreeIter iter)
 		{
 			Gtk.CellRendererText crt = renderer as Gtk.CellRendererText;
-			ICategory category = model.GetValue (iter, 0) as ICategory;
+			Category category = model.GetValue (iter, 0) as Category;
 
 			// CRG: What?  I added this check for null and we don't crash
 			// but I never see anything called unknown
@@ -692,7 +692,7 @@ namespace Tasque
 			}
 		}
 		
-		void RebuildAddTaskMenu (CollectionView<ICategory> categories)
+		void RebuildAddTaskMenu (CollectionView<Category> categories)
 		{
 			Menu menu = new Menu ();
 			
@@ -700,7 +700,7 @@ namespace Tasque
 				if (cat is AllCategory)
 					continue;
 				
-				CategoryMenuItem item = new CategoryMenuItem ((ICategory)cat);
+				CategoryMenuItem item = new CategoryMenuItem ((Category)cat);
 				item.Activated += OnNewTaskByCategory;
 				item.ShowAll ();
 				menu.Add (item);
@@ -720,7 +720,7 @@ namespace Tasque
 				// matching category
 				if (model.GetIterFirst (out iter)) {
 					do {
-						ICategory cat = model.GetValue (iter, 0) as ICategory;
+						Category cat = model.GetValue (iter, 0) as Category;
 						if (cat == null)
 							continue; // Needed for some reason to prevent crashes from some backends
 						if (cat.Name.CompareTo (categoryName) == 0) {
@@ -737,7 +737,7 @@ namespace Tasque
 				// category.
 				if (model.GetIterFirst (out iter)) {
 					// Make sure we can actually get a category
-					ICategory cat = model.GetValue (iter, 0) as ICategory;
+					Category cat = model.GetValue (iter, 0) as Category;
 					if (cat != null)
 						categoryComboBox.SetActiveIter (iter);
 				}
@@ -761,7 +761,7 @@ namespace Tasque
 			dialog.Present ();
 		}
 		
-		private Task CreateTask (string taskText, ICategory category)
+		private Task CreateTask (string taskText, Category category)
 		{
 			Task task = backend.CreateTask (taskText, category);
 			
@@ -914,8 +914,8 @@ namespace Tasque
 			if (!categoryComboBox.GetActiveIter (out iter))
 				return;
 			
-			ICategory category =
-				categoryComboBox.Model.GetValue (iter, 0) as ICategory;
+			Category category =
+				categoryComboBox.Model.GetValue (iter, 0) as Category;
 		
 			// If enabled, attempt to parse due date information
 			// out of the entered task text.
@@ -956,8 +956,8 @@ namespace Tasque
 			// the title of the task.
 			Gtk.TreeIter iter;
 			if (categoryComboBox.GetActiveIter (out iter)) {
-				ICategory selectedCategory =
-					categoryComboBox.Model.GetValue (iter, 0) as ICategory;
+				Category selectedCategory =
+					categoryComboBox.Model.GetValue (iter, 0) as Category;
 				
 				// Check to see if "All" is selected
 				if (selectedCategory is AllCategory) {
@@ -986,8 +986,8 @@ namespace Tasque
 			if (!categoryComboBox.GetActiveIter (out iter))
 				return;
 			
-			ICategory category =
-				categoryComboBox.Model.GetValue (iter, 0) as ICategory;
+			Category category =
+				categoryComboBox.Model.GetValue (iter, 0) as Category;
 				
 			// Update the TaskGroups so they can filter accordingly
 			overdueGroup.Refilter (category);
@@ -1078,7 +1078,7 @@ namespace Tasque
 					 * here in order to enable changing categories. The list of available categories
 					 * is pre-filtered as to not contain the current category and the AllCategory.
 					 */
-					var cvCategories = new CollectionView<ICategory> (Application.Backend.SortedCategories);
+					var cvCategories = new CollectionView<Category> (Application.Backend.Categories);
 					cvCategories.Filter = c => c != null && !(c is AllCategory) && !c.Equals(clickedTask.Category);
 
 					// The categories submenu is only created in case we actually provide at least one category.
@@ -1087,7 +1087,7 @@ namespace Tasque
 						CategoryMenuItem categoryItem;
 
 						foreach (var cat in cvCategories) {
-							categoryItem = new CategoryMenuItem((ICategory)cat);
+							categoryItem = new CategoryMenuItem((Category)cat);
 							categoryItem.Activated += OnChangeCategory;
 							categoryMenu.Add(categoryItem);
 						}
@@ -1176,7 +1176,7 @@ namespace Tasque
 				status = string.Format (Catalog.GetString ("Tasks loaded: {0}"), now);
 				TaskWindow.lastLoadedTime = now;
 				TaskWindow.ShowStatus (status);
-				RebuildAddTaskMenu ((CollectionView<ICategory>)Application.Backend.SortedCategories);
+				RebuildAddTaskMenu ((CollectionView<Category>)Application.Backend.Categories);
 				addTaskEntry.Sensitive = true;
 				categoryComboBox.Sensitive = true;
 				// Keep insensitive text color
@@ -1214,14 +1214,14 @@ namespace Tasque
 		#region Private Classes
 		class CategoryMenuItem : Gtk.MenuItem
 		{
-			private ICategory cat;
+			private Category cat;
 			
-			public CategoryMenuItem (ICategory category) : base (category.Name)
+			public CategoryMenuItem (Category category) : base (category.Name)
 			{
 				cat = category;
 			}
 			
-			public ICategory Category
+			public Category Category
 			{
 				get { return cat; }
 			}
diff --git a/src/tasque/tasque.csproj b/src/tasque/tasque.csproj
index d0a85cf..01a332c 100644
--- a/src/tasque/tasque.csproj
+++ b/src/tasque/tasque.csproj
@@ -159,6 +159,7 @@
     </Reference>
     <Reference Include="notify-sharp, Version=0.4.0.0, Culture=neutral, PublicKeyToken=2df29c54e245917a">
       <Private>False</Private>
+      <Package>notify-sharp</Package>
     </Reference>
     <Reference Include="NDesk.DBus.GLib, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f6716e4f9b2ed099">
       <Private>False</Private>
@@ -198,7 +199,6 @@
     <None Include="Backends\Rtm\RtmNote.cs" />
     <None Include="Backends\Rtm\RtmPreferencesWidget.cs" />
     <None Include="Backends\Rtm\RtmTask.cs" />
-    <None Include="AllCategory.cs" />
   </ItemGroup>
   <ItemGroup>
     <Compile Include="Properties\AssemblyInfo.cs" />



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