[tasque] Large change set



commit c7b5fe09a1f724611c29c06573cdc7c0fd115bbb
Author: Antonius Riha <antoniusriha gmail com>
Date:   Thu Mar 21 10:53:00 2013 +0100

    Large change set

 Makefile.am                                        |    1 -
 build/CommonAssemblyInfo.cs                        |    2 +-
 build/build.csproj                                 |   11 +-
 configure.ac                                       |    2 +-
 data/data.mdproj                                   |    4 +-
 po/po.mdproj                                       |    2 +-
 src/Addins/Backends/Dummy/DummyBackend.cs          |  429 +++++++---------
 src/Addins/Backends/Dummy/DummyBackend.csproj      |   15 +-
 src/Addins/Backends/Dummy/DummyCategory.cs         |   37 --
 .../Backends/Dummy/DummyList.cs}                   |   26 +-
 src/Addins/Backends/Dummy/DummyNote.cs             |   47 +-
 .../Backends/Dummy/DummyObject.cs}                 |   28 +-
 src/Addins/Backends/Dummy/DummyTask.cs             |  201 ++------
 src/Addins/Backends/Dummy/Gtk/DummyPreferences.cs  |    2 +-
 .../Backends/Dummy/NoteRepository.cs}              |   41 +-
 .../Backends/Dummy/Properties/AssemblyInfo.cs      |    3 +
 src/Addins/Backends/Dummy/TaskListRepository.cs    |  127 +++++
 src/Addins/Backends/Dummy/TaskRepository.cs        |  198 +++++++
 .../Backends/Rtm/Extensions.cs}                    |   52 ++-
 .../Backends/Rtm/Gtk/RtmPreferencesWidget.cs       |    2 +-
 src/Addins/Backends/Rtm/Properties/AssemblyInfo.cs |    3 +
 src/Addins/Backends/Rtm/RtmBackend.cs              |  503 +++++--------------
 src/Addins/Backends/Rtm/RtmBackend.csproj          |   22 +-
 .../Backends/Rtm/{RtmCategory.cs => RtmList.cs}    |   29 +-
 src/Addins/Backends/Rtm/RtmNote.cs                 |    6 +-
 .../Backends/Rtm/RtmNoteRepository.cs}             |   56 ++-
 src/Addins/Backends/Rtm/RtmTask.cs                 |  240 +++------
 src/Addins/Backends/Rtm/RtmTaskListRepository.cs   |  156 ++++++
 src/Addins/Backends/Rtm/RtmTaskRepository.cs       |  216 ++++++++
 src/Addins/Backends/Sqlite/SqliteBackend.cs        |  129 +++---
 src/Addins/Backends/Sqlite/SqliteBackend.csproj    |    4 +-
 src/Addins/Backends/Sqlite/SqliteCategory.cs       |   69 ---
 src/Addins/Backends/Sqlite/SqliteList.cs           |   80 +++
 src/Addins/Backends/Sqlite/SqliteTask.cs           |  191 ++-----
 src/Addins/Gtk.Tasque.Columns/CompleteColumn.cs    |    1 +
 src/Addins/Gtk.Tasque.Columns/DueDateColumn.cs     |    8 +-
 .../Gtk.Tasque.Columns/Gtk.Tasque.Columns.csproj   |    6 +-
 src/Addins/Gtk.Tasque.Columns/NotesColumn.cs       |    2 +
 src/Addins/Gtk.Tasque.Columns/PriorityColumn.cs    |    1 +
 .../Gtk.Tasque.Columns/Properties/AssemblyInfo.cs  |    2 +-
 src/Addins/Gtk.Tasque.Columns/TaskBeingEdited.cs   |    2 +-
 src/Addins/Gtk.Tasque.Columns/TaskNameColumn.cs    |    8 +-
 .../CompleteWithTimerColumn.cs                     |    1 +
 .../Gtk.Tasque.TimerCompleteColumns.csproj         |    2 +-
 .../Properties/AssemblyInfo.cs                     |    2 +-
 .../TaskCompleteTimer.cs                           |    2 +-
 .../TaskCompleteTimerStoppedEventArgs.cs           |    2 +-
 .../TaskCompleteTimerTickEventArgs.cs              |    2 +-
 .../Gtk.Tasque.TimerCompleteColumns/TimerColumn.cs |    7 +-
 src/Gtk.Tasque/AppIndicatorTray.cs                 |    3 +-
 src/Gtk.Tasque/CellRendererDate.cs                 |    2 +-
 src/Gtk.Tasque/CompletedTaskGroup.cs               |   30 +-
 src/Gtk.Tasque/DateButton.cs                       |    2 +-
 src/Gtk.Tasque/Defines.cs.in                       |    2 +-
 src/Gtk.Tasque/Gtk.Tasque.csproj                   |   67 ++-
 src/Gtk.Tasque/GtkApplicationBase.cs               |  352 ++++++++-----
 src/Gtk.Tasque/GtkLinuxApplication.cs              |    6 +-
 src/Gtk.Tasque/GtkTray.cs                          |  165 +++----
 src/Gtk.Tasque/GtkWinApplication.cs                |    4 +-
 src/Gtk.Tasque/NoteDialog.cs                       |   25 +-
 src/Gtk.Tasque/NoteWidget.cs                       |    8 +-
 src/Gtk.Tasque/OSXApplication.cs                   |   91 ----
 src/Gtk.Tasque/PreferencesDialog.cs                |  196 ++++----
 src/{tasque => Gtk.Tasque}/Program.cs              |   31 +-
 src/Gtk.Tasque/Properties/AssemblyInfo.cs          |    6 +-
 src/Gtk.Tasque/RemoteControl.cs                    |  127 +++--
 src/Gtk.Tasque/StatusIconTray.cs                   |    2 +-
 src/Gtk.Tasque/TaskCalendar.cs                     |    1 +
 src/Gtk.Tasque/TaskGroup.cs                        |   36 +-
 src/Gtk.Tasque/TaskRowEditingEventArgs.cs          |    5 +-
 src/Gtk.Tasque/TaskView.cs                         |   25 +-
 src/Gtk.Tasque/TaskWindow.cs                       |  389 +++++++-------
 src/Gtk.Tasque/Tasque.exe.Defines.config           |    6 +
 .../Tasque.exe.Defines.config.in                   |    0
 src/{tasque => Gtk.Tasque}/Tasque.exe.config       |    0
 src/Gtk.Tasque/Utilities.cs                        |    3 +-
 src/{tasque => Gtk.Tasque}/tasque.in               |    0
 src/{tasque => Gtk.Tasque}/tasque.pc.in            |    0
 src/Libraries/RtmNet/RtmNet.csproj                 |    2 +-
 src/MonoMac.Tasque/MonoMac.Tasque.csproj           |    2 +-
 src/libtasque/AllCategory.cs                       |   56 --
 src/libtasque/Core/BackendManager.cs               |  216 ++++++++
 .../{IBackendPreferences.cs => Core/INote.cs}      |   23 +-
 src/libtasque/{TaskComparer.cs => Core/ITask.cs}   |   44 ++-
 .../{CategoryComparer.cs => Core/ITaskList.cs}     |   28 +-
 .../ITasqueObject.cs}                              |   23 +-
 .../Impl/Extensions.cs}                            |   34 +-
 .../Impl/IBackendDetachable.cs}                    |   24 +-
 .../Core/Impl/IContainer.cs}                       |   27 +-
 .../Impl/IIdEditable.cs}                           |   22 +-
 .../Impl/IInternalContainee.cs}                    |   20 +-
 .../Impl/IInternalTasqueObject.cs}                 |   22 +-
 .../{TaskComparer.cs => Core/Impl/INotifying.cs}   |   20 +-
 .../InternalBackendManager.TaskListCollection.cs   |  204 +++++++
 src/libtasque/Core/Impl/InternalBackendManager.cs  |  203 +++++++
 src/libtasque/Core/Impl/Note.cs                    |  107 ++++
 src/libtasque/Core/Impl/Task.cs                    |  556 ++++++++++++++++++++
 src/libtasque/Core/Impl/TaskList.cs                |  269 ++++++++++
 src/libtasque/Core/Impl/TasqueObject.cs            |   92 ++++
 src/libtasque/Core/Impl/TasqueObjectCollection.cs  |  157 ++++++
 .../TaskListType.cs}                               |   23 +-
 .../{CategoryComparer.cs => Core/TaskState.cs}     |   50 ++-
 .../BackendExtensionAttribute.cs}                  |   30 +-
 .../Data/BackendInitializationException.cs         |   68 +++
 .../{TaskComparer.cs => Data/Extensions.cs}        |   22 +-
 src/libtasque/{ => Data}/IBackend.cs               |   22 +-
 src/libtasque/Data/IBackend2.cs                    |   94 ++++
 src/libtasque/{ => Data}/IBackendPreferences.cs    |    2 +-
 src/libtasque/Data/ICollectionRepository.cs        |   77 +++
 .../INoteRepository.cs}                            |   23 +-
 .../IRepository.cs}                                |   23 +-
 .../IRepositoryProvider.cs}                        |   23 +-
 .../ITaskListRepository.cs}                        |   20 +-
 src/libtasque/Data/ITaskRepository.cs              |   77 +++
 src/libtasque/Data/TasqueObjectFactory.cs          |   82 +++
 src/libtasque/Data/TransactionException.cs         |   67 +++
 .../{ => DateFormatters}/DateFormatterFactory.cs   |    2 +-
 src/libtasque/{ => DateFormatters}/Extensions.cs   |   27 +-
 .../RegularExpressionFormatter.cs                  |    2 +-
 src/libtasque/{ => DateFormatters}/TaskParser.cs   |    2 +-
 .../{ => DateFormatters}/TranslatableToken.cs      |    2 +-
 src/libtasque/DateFormatters/WeekdayFormatter.cs   |    6 +-
 src/libtasque/ICategory.cs                         |   20 -
 src/libtasque/{TaskComparer.cs => IContainee.cs}   |   15 +-
 src/libtasque/INativeApplication.cs                |   23 -
 src/libtasque/INote.cs                             |   19 -
 .../{IBackendPreferences.cs => INoteCore.cs}       |   23 +-
 src/libtasque/ITask.cs                             |  170 ------
 .../{CategoryComparer.cs => ITaskCore.cs}          |   26 +-
 .../{IBackendPreferences.cs => ITaskListCore.cs}   |   22 +-
 .../{IBackendPreferences.cs => ITasqueCore.cs}     |   22 +-
 src/libtasque/NativeApplication.cs                 |  350 ------------
 src/libtasque/PreferencesKeys.cs                   |   10 +-
 src/libtasque/Properties/AssemblyInfo.cs           |    2 +
 src/libtasque/Task.cs                              |  189 -------
 src/libtasque/TaskGroupModelFactory.cs             |   42 --
 src/libtasque/TaskPriority.cs                      |   35 +-
 src/libtasque/TaskState.cs                         |   27 -
 src/libtasque/Utils/AllList.cs                     |  235 +++++++++
 .../{ => Utils}/CompletedTaskGroupModel.cs         |    5 +-
 src/libtasque/{ => Utils}/Preferences.cs           |    2 +-
 src/libtasque/Utils/TaskComparer.cs                |   98 ++++
 src/libtasque/Utils/TaskCompletionDateComparer.cs  |   70 +++
 src/libtasque/{ => Utils}/TaskGroupModel.cs        |  122 +++--
 .../TaskListComparer.cs}                           |   15 +-
 src/libtasque/libtasque.csproj                     |   92 +++-
 src/tasque/tasque.csproj                           |  123 -----
 tasque.sln                                         |   30 +-
 tests/BackendsFixture.cs                           |   79 ---
 .../TaskComparer.cs => tests/DummyBackendTest.cs   |   28 +-
 tests/TaskParserFixture.cs                         |    1 +
 tests/TasqueTestsSetup.cs                          |  108 ----
 tests/libtasque.Test/Core/Impl/NoteTest.cs         |  129 +++++
 .../Core/Impl/TaskBackendAttachedTest.cs           |   93 ++++
 .../Core/Impl/TaskBackendDetachedTest.cs           |   80 +++-
 tests/libtasque.Test/Core/Impl/TaskTest.cs         |  331 ++++++++++++
 .../Core/Impl/TasqueObjectCollectionSharingTest.cs |   50 ++-
 .../Core/Impl/TasqueObjectCollectionTest.cs        |   84 +++
 tests/libtasque.Test/Core/Impl/TasqueObjectTest.cs |  192 +++++++
 tests/libtasque.Test/libtasque.Test.csproj         |   57 ++
 tests/tests.csproj                                 |   13 +-
 161 files changed, 6583 insertions(+), 3910 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index fbc2134..e3e71a7 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -104,7 +104,6 @@ _BUILDFILES = \
        src/Libraries/RtmNet/RtmNet.csproj \
        src/libtasque/libtasque.csproj \
        src/Gtk.Tasque/Gtk.Tasque.csproj \
-       src/tasque/tasque.csproj \
        src/Addins/Backends/Dummy/DummyBackend.csproj \
        src/Addins/Backends/Eds/EdsBackend.csproj \
        src/Addins/Backends/Hiveminder/HiveminderBackend.csproj \
diff --git a/build/CommonAssemblyInfo.cs b/build/CommonAssemblyInfo.cs
index 257208b..bb0dce7 100644
--- a/build/CommonAssemblyInfo.cs
+++ b/build/CommonAssemblyInfo.cs
@@ -31,4 +31,4 @@ using System.Reflection;
 [assembly: AssemblyCopyright("Copyright (C) 2008-2011 Novell, Inc and Contributors. 
http://live.gnome.org/Tasque";)]
 [assembly: AssemblyTrademark("")]
 [assembly: AssemblyCulture("")]
-[assembly: AssemblyVersion("0.1.13.*")]
+[assembly: AssemblyVersion("0.2.0.*")]
diff --git a/build/build.csproj b/build/build.csproj
index eff2b39..e94adbe 100644
--- a/build/build.csproj
+++ b/build/build.csproj
@@ -12,7 +12,7 @@
     <AssemblyName>build</AssemblyName>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
-    <ReleaseVersion>0.1.13</ReleaseVersion>
+    <ReleaseVersion>0.2.0</ReleaseVersion>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
     <DebugSymbols>True</DebugSymbols>
@@ -46,9 +46,6 @@
     <Proj Include="..\src\libtasque\libtasque.csproj">
       <Link>libtasque.csproj</Link>
     </Proj>
-    <Proj Include="..\src\tasque\tasque.csproj">
-      <Link>tasque.csproj</Link>
-    </Proj>
     <Proj Include="..\src\Libraries\RtmNet\RtmNet.csproj">
       <Link>RtmNet.csproj</Link>
     </Proj>
@@ -100,6 +97,12 @@
     <None Include="..\Makefile.am">
       <Link>Makefile.am</Link>
     </None>
+    <None Include="..\tests\libtasque.Test\libtasque.Test.csproj">
+      <Link>libtasque.Test.csproj</Link>
+    </None>
+    <None Include="..\configure.ac">
+      <Link>configure.ac</Link>
+    </None>
   </ItemGroup>
   <ItemGroup>
     <Folder Include="Addins\" />
diff --git a/configure.ac b/configure.ac
index ae2ae9b..5c4be06 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,7 +1,7 @@
 dnl Warning: This is an automatically generated file, do not edit!
 dnl Process this file with autoconf to produce a configure script.
 AC_PREREQ([2.54])
-AC_INIT([tasque], [0.1.13])
+AC_INIT([tasque], [0.2.0])
 AM_INIT_AUTOMAKE([foreign tar-ustar])
 AM_MAINTAINER_MODE
 
diff --git a/data/data.mdproj b/data/data.mdproj
index 732ec34..ae69751 100644
--- a/data/data.mdproj
+++ b/data/data.mdproj
@@ -8,14 +8,14 @@
     <SchemaVersion>2.0</SchemaVersion>
     <ProjectGuid>{6F2F4BAA-3C60-464D-B757-9DD18FED0BAA}</ProjectGuid>
     <OutputPath>.</OutputPath>
-    <ReleaseVersion>0.1.13</ReleaseVersion>
+    <ReleaseVersion>0.2.0</ReleaseVersion>
     <PackageName>tasque</PackageName>
     <TopBuildDir>..</TopBuildDir>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Linux|AnyCPU' ">
     <CustomCommands>
       <CustomCommands>
-               <Command type="Build" command="xbuild ${ProjectFile}" workingdir="${ProjectDir}" />
+        <Command type="Build" command="xbuild ${ProjectFile}" workingdir="${ProjectDir}" />
         <Command type="AfterBuild" command="xbuild /property:alttarget=install ${ProjectFile}" 
workingdir="${ProjectDir}" />
       </CustomCommands>
     </CustomCommands>
diff --git a/po/po.mdproj b/po/po.mdproj
index 23a2c49..23d9054 100644
--- a/po/po.mdproj
+++ b/po/po.mdproj
@@ -56,7 +56,7 @@
         <Translation isoCode="zh_TW" />
       </translations>
     </translations>
-    <ReleaseVersion>0.1.13</ReleaseVersion>
+    <ReleaseVersion>0.2.0</ReleaseVersion>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)' == 'Default' " />
   <!-- The above is only for the MD Gettext addin, which provides a convenient environment for translation 
-->
diff --git a/src/Addins/Backends/Dummy/DummyBackend.cs b/src/Addins/Backends/Dummy/DummyBackend.cs
index 0b2ac3f..09cdf77 100644
--- a/src/Addins/Backends/Dummy/DummyBackend.cs
+++ b/src/Addins/Backends/Dummy/DummyBackend.cs
@@ -1,287 +1,222 @@
-// DummyBackend.cs created with MonoDevelop
-// User: boyd at 7:10 AM 2/11/2008
-
+//
+// DummyBackend.cs
+//
+// Author:
+//       Antonius Riha <antoniusriha gmail com>
+//
+// Copyright (c) 2013 Antonius Riha
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
 using System;
 using System.Collections.Generic;
-using System.Collections.ObjectModel;
 using System.Linq;
-using Mono.Unix;
-using Tasque.Backends;
+using Tasque.Data;
 using Gtk.Tasque.Backends.Dummy;
-using System.ComponentModel;
 
 namespace Tasque.Backends.Dummy
 {
-       public class DummyBackend : IBackend
+       [BackendExtension ("Dummy")]
+       public class DummyBackend : IBackend2
        {
-               private int newTaskId;
-               private bool initialized;
-               private bool configured = true;
-               
-               ObservableCollection<ITask> taskStore;
-               ObservableCollection<ICategory> categoryListStore;
-               ReadOnlyObservableCollection<ITask> readOnlyTaskStore;
-               ReadOnlyObservableCollection<ICategory> readOnlyCategoryStore;
-               
-               TaskComparer taskComparer;
-               CategoryComparer categoryComparer;
-               
-               public event BackendInitializedHandler BackendInitialized;
-               public event BackendSyncStartedHandler BackendSyncStarted;
-               public event BackendSyncFinishedHandler BackendSyncFinished;
-               
-               DummyCategory homeCategory;
-               DummyCategory workCategory;
-               DummyCategory projectsCategory;
-               
                public DummyBackend ()
                {
-                       initialized = false;
-                       newTaskId = 0;
-                       taskStore = new ObservableCollection<ITask> ();
-                       categoryListStore = new ObservableCollection<ICategory> ();
-                       readOnlyTaskStore = new ReadOnlyObservableCollection<ITask> (taskStore);
-                       readOnlyCategoryStore
-                               = new ReadOnlyObservableCollection<ICategory> (categoryListStore);
-                       taskComparer = new TaskComparer ();
-                       categoryComparer = new CategoryComparer ();
+                       // Create fake backend content
+                       var sharedTask1 = new DummyTask ("Buy some nails") {
+                               DueDate = DateTime.Now.AddDays (1),
+                               Priority = 3
+                       };
+
+                       var sharedTask2 = new DummyTask ("Replace burnt out lightbulb") {
+                               DueDate = DateTime.Now,
+                               Priority = 1
+                       };
+
+                       var complTask1 = new DummyTask ("Call Roger") {
+                               DueDate = DateTime.Now.AddDays (-1),
+                       };
+
+                       var complTask2 = new DummyTask ("Test task overdue") {
+                               DueDate = DateTime.Now.AddDays (-89)
+                       };
+
+                       var notesTask1 = new DummyTask ("This task has a note.") {
+                               DueDate = DateTime.Now.AddDays (2),
+                               Priority = 4
+                       };
+                       notesTask1.TaskNotes.Add (new DummyNote ("This is the note."));
+
+                       var homeList = new DummyList ("Home");
+                       homeList.Tasks.Add (sharedTask1);
+                       homeList.Tasks.Add (sharedTask2);
+                       homeList.Tasks.Add (complTask1);
+                       homeList.Tasks.Add (new DummyTask ("File taxes") {
+                               DueDate = new DateTime (2008, 4, 1)
+                       });
+                       homeList.Tasks.Add (new DummyTask ("Pay storage rental fee") {
+                               DueDate = DateTime.Now.AddDays (1)
+                       });
+
+                       var workList = new DummyList ("Work");
+                       workList.Tasks.Add (complTask2);
+                       workList.Tasks.Add (notesTask1);
+
+                       var projectsList = new DummyList ("Projects");
+                       projectsList.Tasks.Add (sharedTask1);
+                       projectsList.Tasks.Add (sharedTask2);
+                       projectsList.Tasks.Add (new DummyTask ("Purchase lumber") {
+                               DueDate = DateTime.Now.AddDays (1),
+                               Priority = 5
+                       });
+                       projectsList.Tasks.Add (new DummyTask ("Estimate drywall requirements") {
+                               DueDate = DateTime.Now.AddDays (1),
+                               Priority = 1
+                       });
+                       projectsList.Tasks.Add (new DummyTask ("Borrow framing nailer from Ben") {
+                               DueDate = DateTime.Now.AddDays (1),
+                               Priority = 4,
+                       });
+                       projectsList.Tasks.Add (new DummyTask ("Call for an insulation estimate") {
+                               DueDate = DateTime.Now.AddDays (1),
+                               Priority = 3
+                       });
+                       projectsList.Tasks.Add (new DummyTask ("Place carpet order"));
+
+                       DummyLists = new List<DummyList> {
+                               homeList,
+                               workList,
+                               projectsList
+                       };
                }
                
-               #region Public Properties
-               public string Name
-               {
-                       get { return "Debugging System"; }
+               public bool IsConfigured { get; private set; }
+
+               public bool IsInitialized { get; private set; }
+
+               public IBackendPreferences Preferences {
+                       get { return new DummyPreferences (); }
                }
-               
-               /// <value>
-               /// All the tasks including ITaskDivider items.
-               /// </value>
-               public ICollection<ITask> Tasks
+
+               public void Initialize (IPreferences preferences)
                {
-                       get { return readOnlyTaskStore; }
+                       if (preferences == null)
+                               throw new ArgumentNullException ("preferences");
+                       if (IsInitialized)
+                               return;
+
+                       // Establish connection to backend
+                       // Nothing to do for Dummy Backend
+
+                       // Setup repos
+                       noteRepo = new NoteRepository (this);
+                       taskListRepo = new TaskListRepository (this);
+                       taskRepo = new TaskRepository (this);
+
+                       // Setup TasqueObjectFactory
+                       Factory = new TasqueObjectFactory (
+                               taskListRepo, taskRepo, noteRepo);
+
+                       IsConfigured = true;
+                       IsInitialized = true;
+                       if (Initialized != null)
+                               Initialized (this, EventArgs.Empty);
                }
-               
-               /// <value>
-               /// This returns all the task lists (categories) that exist.
-               /// </value>
-               public ICollection<ICategory> Categories
+
+               public IEnumerable<ITaskListCore> GetAll ()
                {
-                       get { return readOnlyCategoryStore; }
+                       foreach (var item in DummyLists) {
+                               yield return Factory.CreateTaskList (
+                                       item.Id.ToString (), item.ListName);
+                       }
                }
-               
-               /// <value>
-               /// Indication that the dummy backend is configured
-               /// </value>
-               public bool Configured 
+
+               public ITaskListCore GetBy (string id)
                {
-                       get { return configured; }
+                       var dummyList = GetTaskListBy (id);
+                       return Factory.CreateTaskList (id, dummyList.ListName);
                }
-               
-               /// <value>
-               /// Inidication that the backend is initialized
-               /// </value>
-               public bool Initialized
+
+               public void Create (ITaskListCore taskList)
                {
-                       get { return initialized; }
-               }               
-               #endregion // Public Properties
-               
-               #region Public Methodsopen source contributors badges
-               public ITask CreateTask (string taskName, ICategory category)           
+                       throw new NotImplementedException ();
+               }
+
+               public void Delete (ITaskListCore taskList)
                {
-                       // 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 Tasque.AllCategory)
-                               task.Category = workCategory; // Default to work
-                       else
-                               task.Category = category;
-                       
-                       AddTask (task);
-                       newTaskId++;
-                       
-                       task.PropertyChanged += HandlePropertyChanged;
-                       
-                       return task;
+                       throw new NotImplementedException ();
                }
-               
-               public void DeleteTask(ITask task)
-               {}
-               
-               public void Refresh()
-               {}
 
-               public void Initialize (IPreferences preferences)
+               public void Dispose ()
                {
-                       if (preferences == null)
-                               throw new ArgumentNullException ("preferences");
+                       if (disposed)
+                               return;
+                       disposed = true;
+
+                       // Cleanup and disconnect from backend
+                       // Nothing to do for Dummy Backend
 
-                       //
-                       // Add in the "All" Category
-                       //
-                       AddCategory (new AllCategory (preferences));
-                       
-                       //
-                       // Add in some fake categories
-                       //
-                       homeCategory = new DummyCategory ("Home");
-                       AddCategory (homeCategory);
-                       
-                       workCategory = new DummyCategory ("Work");
-                       AddCategory (workCategory);
-                       
-                       projectsCategory = new DummyCategory ("Projects");
-                       AddCategory (projectsCategory);
-                       
-                       //
-                       // Add in some fake tasks
-                       //
-                       
-                       DummyTask task = new DummyTask (this, newTaskId, "Buy some nails");
-                       task.Category = projectsCategory;
-                       task.DueDate = DateTime.Now.AddDays (1);
-                       task.Priority = TaskPriority.Medium;
-                       AddTask (task);
-                       task.PropertyChanged += HandlePropertyChanged;
-                       newTaskId++;
-                       
-                       task = new DummyTask (this, newTaskId, "Call Roger");
-                       task.Category = homeCategory;
-                       task.DueDate = DateTime.Now.AddDays (-1);
-                       task.Complete ();
-                       task.CompletionDate = task.DueDate;
-                       AddTask (task);
-                       task.PropertyChanged += HandlePropertyChanged;
-                       newTaskId++;
-                       
-                       task = new DummyTask (this, newTaskId, "Replace burnt out lightbulb");
-                       task.Category = homeCategory;
-                       task.DueDate = DateTime.Now;
-                       task.Priority = TaskPriority.Low;
-                       AddTask (task);
-                       task.PropertyChanged += HandlePropertyChanged;
-                       newTaskId++;
-                       
-                       task = new DummyTask (this, newTaskId, "File taxes");
-                       task.Category = homeCategory;
-                       task.DueDate = new DateTime (2008, 4, 1);
-                       AddTask (task);
-                       task.PropertyChanged += HandlePropertyChanged;
-                       newTaskId++;
-                       
-                       task = new DummyTask (this, newTaskId, "Purchase lumber");
-                       task.Category = projectsCategory;
-                       task.DueDate = DateTime.Now.AddDays (1);
-                       task.Priority = TaskPriority.High;
-                       AddTask (task);
-                       task.PropertyChanged += HandlePropertyChanged;
-                       newTaskId++;
-                                               
-                       task = new DummyTask (this, newTaskId, "Estimate drywall requirements");
-                       task.Category = projectsCategory;
-                       task.DueDate = DateTime.Now.AddDays (1);
-                       task.Priority = TaskPriority.Low;
-                       AddTask (task);
-                       task.PropertyChanged += HandlePropertyChanged;
-                       newTaskId++;
-                       
-                       task = new DummyTask (this, newTaskId, "Borrow framing nailer from Ben");
-                       task.Category = projectsCategory;
-                       task.DueDate = DateTime.Now.AddDays (1);
-                       task.Priority = TaskPriority.High;
-                       AddTask (task);
-                       task.PropertyChanged += HandlePropertyChanged;
-                       newTaskId++;
-                       
-                       task = new DummyTask (this, newTaskId, "Call for an insulation estimate");
-                       task.Category = projectsCategory;
-                       task.DueDate = DateTime.Now.AddDays (1);
-                       task.Priority = TaskPriority.Medium;
-                       AddTask (task);
-                       task.PropertyChanged += HandlePropertyChanged;
-                       newTaskId++;
-                       
-                       task = new DummyTask (this, newTaskId, "Pay storage rental fee");
-                       task.Category = homeCategory;
-                       task.DueDate = DateTime.Now.AddDays (1);
-                       task.Priority = TaskPriority.None;
-                       AddTask (task);
-                       task.PropertyChanged += HandlePropertyChanged;
-                       newTaskId++;
-                       
-                       task = new DummyTask (this, newTaskId, "Place carpet order");
-                       task.Category = projectsCategory;
-                       task.Priority = TaskPriority.None;
-                       AddTask (task);
-                       task.PropertyChanged += HandlePropertyChanged;
-                       newTaskId++;
-                       
-                       task = new DummyTask (this, newTaskId, "Test task overdue");
-                       task.Category = workCategory;
-                       task.DueDate = DateTime.Now.AddDays (-89);
-                       task.Priority = TaskPriority.None;
-                       task.Complete ();
-                       AddTask (task);
-                       task.PropertyChanged += HandlePropertyChanged;
-                       newTaskId++;
-                       
-                       initialized = true;
-                       if(BackendInitialized != null) {
-                               BackendInitialized();
-                       }               
+                       if (Disposed != null)
+                               Disposed (this, EventArgs.Empty);
                }
 
-               public void Dispose () {}
-               
-               public IBackendPreferences Preferences
-               {
-                       get {
-                               // TODO: Replace this with returning null once things are going
-                               // so that the Preferences Dialog doesn't waste space.
-                               return new DummyPreferences ();
-                       }
+               public event EventHandler Disposed;
+               public event EventHandler Initialized;
+               public event EventHandler NeedsConfiguration;
+
+               #region Explicit content
+               INoteRepository IRepositoryProvider<INoteRepository>.Repository {
+                       get { return noteRepo; }
                }
-               #endregion // Public Methods
-               
-               #region Private Methods
-               internal void DeleteTask (DummyTask task)
-               {
-                       if (taskStore.Remove (task))
-                               task.PropertyChanged -= HandlePropertyChanged;
+
+               ITaskListRepository IRepositoryProvider<ITaskListRepository>.Repository {
+                       get { return taskListRepo; }
                }
+
+               ITaskRepository IRepositoryProvider<ITaskRepository>.Repository {
+                       get { return taskRepo; }
+               }
+               #endregion
+
+               internal TasqueObjectFactory Factory { get; private set; }
+
+               internal List<DummyList> DummyLists { get; private set; }
                
-               void AddCategory (ICategory category)
+               internal DummyNote GetNoteBy (string id)
                {
-                       var index = categoryListStore.Count;
-                       var valIdx = categoryListStore.Select ((val, idx) => new { val, idx })
-                               .FirstOrDefault (x => categoryComparer.Compare (x.val, category) > 0);
-                       if (valIdx != null)
-                               index = valIdx.idx;
-                       categoryListStore.Insert (index, category);
+                       return DummyLists.SelectMany (l => l.Tasks)
+                               .SelectMany (t => t.TaskNotes)
+                               .First (n => n.Id.ToString () == id);
                }
                
-               void AddTask (DummyTask task)
+               internal DummyTask GetTaskBy (string id)
                {
-                       var index = taskStore.Count;
-                       var valIdx = taskStore.Select ((val, idx) => new { val, idx })
-                               .FirstOrDefault (t => taskComparer.Compare (t.val, task) > 0);
-                       if (valIdx != null)
-                               index = valIdx.idx;
-                       
-                       taskStore.Insert (index, task);
+                       return DummyLists.SelectMany (l => l.Tasks)
+                               .First (t => t.Id.ToString () == id);
                }
                
-               void HandlePropertyChanged (object sender, PropertyChangedEventArgs e)
+               internal DummyList GetTaskListBy (string id)
                {
-                       // when a property changes (any property atm), "reorder" tasks
-                       var task = (DummyTask)sender;
-                       if (taskStore.Remove (task))
-                               AddTask (task);
+                       return DummyLists.Single (l => l.Id.ToString () == id);
                }
-               #endregion // Private Methods
-               
-               #region Event Handlers
-               #endregion // Event Handlers
+
+               bool disposed;
+               INoteRepository noteRepo;
+               ITaskListRepository taskListRepo;
+               ITaskRepository taskRepo;
        }
 }
diff --git a/src/Addins/Backends/Dummy/DummyBackend.csproj b/src/Addins/Backends/Dummy/DummyBackend.csproj
index ee106b1..0332759 100644
--- a/src/Addins/Backends/Dummy/DummyBackend.csproj
+++ b/src/Addins/Backends/Dummy/DummyBackend.csproj
@@ -12,7 +12,7 @@
     <AssemblyName>DummyBackend</AssemblyName>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
-    <ReleaseVersion>0.1.13</ReleaseVersion>
+    <ReleaseVersion>0.2.0</ReleaseVersion>
     <BuildEnabled>$(EnableBackendDummy)</BuildEnabled>
     <PackageName>tasque</PackageName>
     <TopBuildDir>..\..\..\..</TopBuildDir>
@@ -35,26 +35,37 @@
     <Reference Include="System" />
     <Reference Include="gtk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f">
       <Private>False</Private>
+      <Package>gtk-sharp-2.0</Package>
     </Reference>
     <Reference Include="Mono.Posix" />
     <Reference Include="glib-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f">
       <Private>False</Private>
+      <Package>glib-sharp-2.0</Package>
     </Reference>
     <Reference Include="atk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f">
       <Private>False</Private>
+      <Package>gtk-sharp-2.0</Package>
     </Reference>
     <Reference Include="System.Core" />
+    <Reference Include="Mono.Addins, Version=0.6.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756">
+      <Private>False</Private>
+      <Package>mono-addins</Package>
+    </Reference>
   </ItemGroup>
   <ItemGroup>
     <Compile Include="DummyTask.cs" />
     <Compile Include="DummyNote.cs" />
-    <Compile Include="DummyCategory.cs" />
     <Compile Include="DummyBackend.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="..\..\..\..\build\CommonAssemblyInfo.cs">
       <Link>Properties\CommonAssemblyInfo.cs</Link>
     </Compile>
     <Compile Include="Gtk\DummyPreferences.cs" />
+    <Compile Include="DummyList.cs" />
+    <Compile Include="DummyObject.cs" />
+    <Compile Include="TaskRepository.cs" />
+    <Compile Include="NoteRepository.cs" />
+    <Compile Include="TaskListRepository.cs" />
   </ItemGroup>
   <ItemGroup>
     <ProjectReference Include="..\..\..\libtasque\libtasque.csproj">
diff --git a/src/libtasque/TaskComparer.cs b/src/Addins/Backends/Dummy/DummyList.cs
similarity index 74%
copy from src/libtasque/TaskComparer.cs
copy to src/Addins/Backends/Dummy/DummyList.cs
index 1285fe1..4676e0f 100644
--- a/src/libtasque/TaskComparer.cs
+++ b/src/Addins/Backends/Dummy/DummyList.cs
@@ -1,10 +1,10 @@
 //
-// TaskComparer.cs
+// DummyList.cs
 //
 // Author:
 //       Antonius Riha <antoniusriha gmail com>
 //
-// Copyright (c) 2012 Antonius Riha
+// Copyright (c) 2013 Antonius Riha
 //
 // Permission is hereby granted, free of charge, to any person obtaining a copy
 // of this software and associated documentation files (the "Software"), to deal
@@ -23,18 +23,24 @@
 // 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.Generic;
+using System.Collections.ObjectModel;
 
-namespace Tasque
+namespace Tasque.Backends.Dummy
 {
-       public class TaskComparer : Comparer<ITask>
+       public class DummyList : DummyObject
        {
-               public override int Compare (ITask x, ITask y)
+               public DummyList ()
                {
-                       if (x == null || y == null)
-                               return 0;
-                       
-                       return (x.CompareTo (y));
+                       Tasks = new Collection<DummyTask> ();
                }
+
+               public DummyList (string listName) : this ()
+               {
+                       ListName = listName;
+               }
+
+               public string ListName { get; set; }
+
+               public Collection<DummyTask> Tasks { get; private set; }
        }
 }
diff --git a/src/Addins/Backends/Dummy/DummyNote.cs b/src/Addins/Backends/Dummy/DummyNote.cs
index f5e727b..b4ae99f 100644
--- a/src/Addins/Backends/Dummy/DummyNote.cs
+++ b/src/Addins/Backends/Dummy/DummyNote.cs
@@ -1,29 +1,38 @@
-// DummyNote.cs created with MonoDevelop
-// User: calvin at 10:56 AM 2/12/2008
 //
-// To change standard headers go to Edit->Preferences->Coding->Standard Headers
+// DummyNote.cs
 //
-
-using System;
-using Tasque;
+// Author:
+//       Antonius Riha <antoniusriha gmail com>
+//
+// Copyright (c) 2013 Antonius Riha
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
 
 namespace Tasque.Backends.Dummy
 {
-       public class DummyNote : INote
-       {
-               public string Name
-               {
-                       get { return ""; }
-                       set { // TODO: Implement something 
-                       }
-               }
-   
-               public string Text
+       public class DummyNote : DummyObject
+       {   
+               public DummyNote (string text)
                {
-                       get { return ""; }
-                       set { // TODO: Implement something 
-                       }
+                       Text = text;
                }
 
+               public string Text { get; set; }
        }
 }
\ No newline at end of file
diff --git a/src/libtasque/IBackendPreferences.cs b/src/Addins/Backends/Dummy/DummyObject.cs
similarity index 82%
copy from src/libtasque/IBackendPreferences.cs
copy to src/Addins/Backends/Dummy/DummyObject.cs
index 1f1a236..5eb84b3 100644
--- a/src/libtasque/IBackendPreferences.cs
+++ b/src/Addins/Backends/Dummy/DummyObject.cs
@@ -1,21 +1,21 @@
-// 
-// IBackendPreferences.cs
-//  
+//
+// DummyObject.cs
+//
 // Author:
 //       Antonius Riha <antoniusriha gmail com>
-// 
-// Copyright (c) 2012 Antonius Riha
-// 
+//
+// Copyright (c) 2013 Antonius Riha
+//
 // Permission is hereby granted, free of charge, to any person obtaining a copy
 // of this software and associated documentation files (the "Software"), to deal
 // in the Software without restriction, including without limitation the rights
 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 // copies of the Software, and to permit persons to whom the Software is
 // furnished to do so, subject to the following conditions:
-// 
+//
 // The above copyright notice and this permission notice shall be included in
 // all copies or substantial portions of the Software.
-// 
+//
 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -24,9 +24,17 @@
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 // THE SOFTWARE.
 
-namespace Tasque.Backends
+namespace Tasque.Backends.Dummy
 {
-       public interface IBackendPreferences
+       public class DummyObject
        {
+               static int idCounter;
+
+               public DummyObject ()
+               {
+                       Id = ++idCounter;
+               }
+
+               public int Id { get; private set; }
        }
 }
diff --git a/src/Addins/Backends/Dummy/DummyTask.cs b/src/Addins/Backends/Dummy/DummyTask.cs
index e0f5dee..36ce04e 100644
--- a/src/Addins/Backends/Dummy/DummyTask.cs
+++ b/src/Addins/Backends/Dummy/DummyTask.cs
@@ -1,174 +1,69 @@
-// DummyTask.cs created with MonoDevelop
-// User: boyd at 8:50 PM 2/10/2008
-
+//
+// DummyTask.cs
+//
+// Author:
+//       Antonius Riha <antoniusriha gmail com>
+//
+// Copyright (c) 2013 Antonius Riha
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
 using System;
-using Tasque;
 using System.Collections.Generic;
 
 namespace Tasque.Backends.Dummy
 {
-       public class DummyTask : Task
+       public class DummyTask : DummyObject
        {
-               DummyBackend backend;
-               string name;
-               DateTime dueDate;
-               DateTime completionDate;
-               TaskPriority priority;
-               TaskState state;
-               int id;
-               DummyCategory category;
-               
-               public DummyTask(DummyBackend backend, int id, string taskName)
-               {
-                       this.backend = backend;
-                       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;
-               }
-               
-               #region Public Properties
-               
-               public int DummyId
+               public DummyTask ()
                {
-                       get { return id; }
-                       set { id = value; }
+                       DueDate = DateTime.MaxValue;
+                       CompletionDate = DateTime.MaxValue;
+                       TaskNotes = new List<DummyNote> ();
                }
 
-               public override string Id
+               public DummyTask (string text) : this ()
                {
-                       get { return id.ToString(); }
+                       Text = text;
                }
 
-               
-               public override string Name
-               {
-                       get { return name; }
-                       set {
-Logger.Debug ("Setting new task name");
-                               OnPropertyChanging ("Name");
-                               if (value == null)
-                                       name = string.Empty;
-                               
-                               name = value.Trim ();
-                               OnPropertyChanged ("Name");
-                       }
-               }
-               
-               public override DateTime DueDate
-               {
-                       get { return dueDate; }
-                       set {
-Logger.Debug ("Setting new task due date");
-                               OnPropertyChanging ("DueDate");
-                               dueDate = value;
-                               OnPropertyChanged ("DueDate");
-                       }
-               }
-               
-               public override DateTime CompletionDate
-               {
-                       get { return completionDate; }
-                       set {
-Logger.Debug ("Setting new task completion date");
-                               OnPropertyChanging ("CompletionDate");
-                               completionDate = value;
-                               OnPropertyChanged ("CompletionDate");
-                       }
-               }
-               
-               public override bool IsComplete
-               {
-                       get { return state == TaskState.Completed; }
-               }
-               
-               public override TaskPriority Priority
-               {
-                       get { return priority; }
-                       set {
-Logger.Debug ("Setting new task priority");
-                               OnPropertyChanging ("Priority");
-                               priority = value;
-                               OnPropertyChanged ("Priority");
-                       }
-               }
+               public bool IsCompleted { get; private set; }
 
-               public override bool HasNotes
-               {
-                       get { return true; }
-               }
-               
-               public override NoteSupport NoteSupport
-               {
-                       get { return NoteSupport.Multiple; }
-               }
-               
-               public override TaskState State
-               {
-                       get { return state; }
-               }
-               
-               public override ICategory Category
-               {
-                       get { return category; } 
-                       set {
-                               category = value as DummyCategory;
-                       }
-               }
-               
-               public override List<INote> Notes
-               {
-                       get { return null; }
-               }               
-               
-               #endregion // Public Properties
-               
-               #region Public Methods
-               public override void Activate ()
-               {
-Logger.Debug ("DummyTask.Activate ()");
-                       SetState (TaskState.Active);
-                       CompletionDate = DateTime.MinValue;
-               }
-               
-               public override void Complete ()
-               {
-                       Logger.Debug ("DummyTask.Complete ()");
-                       SetState (TaskState.Completed);
-                       CompletionDate = DateTime.Now;
-               }
-               
-               public override void Delete ()
-               {
-Logger.Debug ("DummyTask.Delete ()");
-                       SetState (TaskState.Deleted);
-                       backend.DeleteTask (this);
-               }
-               
-               public override INote CreateNote(string text)
-               {
-                       return null;
-               }
-               
-               public override void DeleteNote(INote note)
-               {
-               }
+               public string Text { get; set; }
+
+               public DateTime CompletionDate { get; private set; }
+
+               public DateTime DueDate { get; set; }
 
-               public override void SaveNote(INote note)
+               public int Priority { get; set; }
+
+               public List<DummyNote> TaskNotes { get; private set; }
+
+               public void CompleteTask ()
                {
+                       IsCompleted = true;
+                       CompletionDate = DateTime.Now;
                }
 
-               #endregion // Public Methods
-
-               void SetState (TaskState value)
+               public void RevertCompletion ()
                {
-                       if (value == state)
-                               return;
-                       OnPropertyChanging ("State");
-                       state = value;
-                       OnPropertyChanged ("State");
+                       IsCompleted = false;
+                       CompletionDate = DateTime.MaxValue;
                }
        }
 }
diff --git a/src/Addins/Backends/Dummy/Gtk/DummyPreferences.cs 
b/src/Addins/Backends/Dummy/Gtk/DummyPreferences.cs
index 0834c67..ed66131 100644
--- a/src/Addins/Backends/Dummy/Gtk/DummyPreferences.cs
+++ b/src/Addins/Backends/Dummy/Gtk/DummyPreferences.cs
@@ -24,7 +24,7 @@
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 // THE SOFTWARE.
 using Gtk;
-using Tasque.Backends;
+using Tasque.Data;
 
 namespace Gtk.Tasque.Backends.Dummy
 {
diff --git a/src/libtasque/CategoryComparer.cs b/src/Addins/Backends/Dummy/NoteRepository.cs
similarity index 64%
copy from src/libtasque/CategoryComparer.cs
copy to src/Addins/Backends/Dummy/NoteRepository.cs
index b81fcfa..50c6e33 100644
--- a/src/libtasque/CategoryComparer.cs
+++ b/src/Addins/Backends/Dummy/NoteRepository.cs
@@ -1,10 +1,10 @@
 //
-// CategoryComparer.cs
+// NoteRepository.cs
 //
 // Author:
 //       Antonius Riha <antoniusriha gmail com>
 //
-// Copyright (c) 2012 Antonius Riha
+// Copyright (c) 2013 Antonius Riha
 //
 // Permission is hereby granted, free of charge, to any person obtaining a copy
 // of this software and associated documentation files (the "Software"), to deal
@@ -23,23 +23,34 @@
 // 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.Generic;
+using System;
+using Tasque.Data;
 
-namespace Tasque
+namespace Tasque.Backends.Dummy
 {
-       public class CategoryComparer : Comparer<ICategory>
+       public class NoteRepository : INoteRepository
        {
-               public override int Compare (ICategory x, ICategory y)
+               public NoteRepository (DummyBackend backend)
                {
-                       if (x == null || y == null)
-                               return 0;
-                       
-                       if (x is AllCategory)
-                               return -1;
-                       else if (y is AllCategory)
-                               return 1;
-                       
-                       return (x.Name.CompareTo (y.Name));
+                       if (backend == null)
+                               throw new ArgumentNullException ("backend");
+                       this.backend = backend;
                }
+               
+               public bool CanBelongToMultipleTasks { get { return false; } }
+
+               public string UpdateTitle (INoteCore note, string title)
+               {
+                       return null;
+               }
+
+               public string UpdateText (INoteCore note, string text)
+               {
+                       var dummyNote = backend.GetNoteBy (note.Id);
+                       dummyNote.Text = text;
+                       return text;
+               }
+
+               DummyBackend backend;
        }
 }
diff --git a/src/Addins/Backends/Dummy/Properties/AssemblyInfo.cs 
b/src/Addins/Backends/Dummy/Properties/AssemblyInfo.cs
index eb7fc97..9924e22 100644
--- a/src/Addins/Backends/Dummy/Properties/AssemblyInfo.cs
+++ b/src/Addins/Backends/Dummy/Properties/AssemblyInfo.cs
@@ -24,6 +24,9 @@
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 // THE SOFTWARE.
 using System.Reflection;
+using Mono.Addins;
 
 [assembly: AssemblyTitle("DummyBackend")]
 [assembly: AssemblyDescription("Dummy backend for Tasque. Serves debug purposes.")]
+[assembly: Addin]
+[assembly: AddinDependency ("libtasque", "0.2.0")]
\ No newline at end of file
diff --git a/src/Addins/Backends/Dummy/TaskListRepository.cs b/src/Addins/Backends/Dummy/TaskListRepository.cs
new file mode 100644
index 0000000..931850f
--- /dev/null
+++ b/src/Addins/Backends/Dummy/TaskListRepository.cs
@@ -0,0 +1,127 @@
+//
+// TaskListRepository.cs
+//
+// Author:
+//       Antonius Riha <antoniusriha gmail com>
+//
+// Copyright (c) 2013 Antonius Riha
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Tasque.Data;
+
+namespace Tasque.Backends.Dummy
+{
+       public class TaskListRepository : ITaskListRepository
+       {
+               public TaskListRepository (DummyBackend backend)
+               {
+                       if (backend == null)
+                               throw new ArgumentNullException ("backend");
+                       this.backend = backend;
+               }
+
+               public bool CanChangeName (ITaskListCore taskList)
+               {
+                       return true;
+               }
+
+               public string UpdateName (ITaskListCore taskList, string name)
+               {
+                       var dummyList = backend.GetTaskListBy (taskList.Id);
+                       dummyList.ListName = name;
+                       return name;
+               }
+
+               public bool SupportsSharingItemsWithOtherCollections {
+                       get { return true; }
+               }
+
+               public IEnumerable<ITaskCore> GetAll (ITaskListCore container)
+               {
+                       var dummyList = backend.GetTaskListBy (container.Id);
+                       foreach (var dummyTask in dummyList.Tasks)
+                               yield return CreateTask (dummyTask);
+               }
+
+               public ITaskCore GetBy (ITaskListCore container, string id)
+               {
+                       return CreateTask (backend.GetTaskBy (id));
+               }
+
+               public void AddNew (ITaskListCore taskList, ITaskCore task)
+               {
+                       var dummyList = backend.GetTaskListBy (taskList.Id);
+                       
+                       var dummyTask = new DummyTask (task.Text) {
+                               DueDate = task.DueDate == DateTime.MaxValue
+                               ? DateTime.MinValue : task.DueDate,
+                               Priority = (int)task.Priority
+                       };
+
+                       dummyList.Tasks.Add (dummyTask);
+               }
+
+               public void Add (ITaskListCore taskList, ITaskCore task)
+               {
+                       var dummyList = backend.GetTaskListBy (taskList.Id);
+                       var dummyTask = backend.GetTaskBy (task.Id);
+                       dummyList.Tasks.Add (dummyTask);
+               }
+
+               public void ClearAll (ITaskListCore taskList)
+               {
+                       var dummyList = backend.GetTaskListBy (taskList.Id);
+                       dummyList.Tasks.Clear ();
+               }
+
+               public void Remove (ITaskListCore taskList, ITaskCore task)
+               {
+                       var dummyList = backend.GetTaskListBy (taskList.Id);
+                       var dummyTask = dummyList.Tasks.Single (
+                               t => t.Id.ToString () == task.Id);
+                       dummyList.Tasks.Remove (dummyTask);
+               }
+
+               ITaskCore CreateTask (DummyTask dummyTask)
+               {
+                       ITaskCore task;
+                       if (dummyTask.IsCompleted) {
+                               task = backend.Factory.CreateCompletedTask (
+                                       dummyTask.Id.ToString (), dummyTask.Text,
+                                       dummyTask.CompletionDate);
+                       } else {
+                               task = backend.Factory.CreateTask (
+                                       dummyTask.Id.ToString (), dummyTask.Text);
+                       }
+                       
+                       task.DueDate = dummyTask.DueDate == DateTime.MaxValue
+                               ? DateTime.MinValue : dummyTask.DueDate;
+                       
+                       task.Priority = dummyTask.Priority > 3 ? TaskPriority.High
+                               : (TaskPriority)dummyTask.Priority;
+                       
+                       return task;
+               }
+
+               DummyBackend backend;
+       }
+}
diff --git a/src/Addins/Backends/Dummy/TaskRepository.cs b/src/Addins/Backends/Dummy/TaskRepository.cs
new file mode 100644
index 0000000..3f6a7b6
--- /dev/null
+++ b/src/Addins/Backends/Dummy/TaskRepository.cs
@@ -0,0 +1,198 @@
+//
+// TaskBackend.cs
+//
+// Author:
+//       Antonius Riha <antoniusriha gmail com>
+//
+// Copyright (c) 2013 Antonius Riha
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Tasque.Data;
+
+namespace Tasque.Backends.Dummy
+{
+       using INoteCollectionRepo = ICollectionRepository<INoteCore, ITaskCore>;
+       using ITaskCollectionRepo = ICollectionRepository<ITaskCore, ITaskCore>;
+
+       public class TaskRepository : ITaskRepository
+       {
+               const string NestedTasksErrMsg = "Nested tasks are not supported.";
+
+               public TaskRepository (DummyBackend backend)
+               {
+                       if (backend == null)
+                               throw new ArgumentNullException ("backend");
+                       this.backend = backend;
+               }
+               
+               public bool SupportsDiscarding { get { return false; } }
+               
+               public bool SupportsNestedTasks { get { return false; } }
+               
+               public NoteSupport NoteSupport { get { return NoteSupport.Multiple; } }
+               
+               public void Activate (ITaskCore task)
+               {
+                       var dummyTask = backend.GetTaskBy (task.Id);
+                       dummyTask.RevertCompletion ();
+               }
+               
+               public DateTime Complete (ITaskCore task, DateTime completionDate)
+               {
+                       var dummyTask = backend.GetTaskBy (task.Id);
+                       dummyTask.CompleteTask ();
+                       return dummyTask.CompletionDate;
+               }
+               
+               public void Discard (ITaskCore task)
+               {
+                       throw new NotSupportedException ("Discarding is not supported.");
+               }
+               
+               public DateTime UpdateDueDate (ITaskCore task, DateTime dueDate)
+               {
+                       var dummyTask = backend.GetTaskBy (task.Id);
+                       dummyTask.DueDate = dueDate == DateTime.MinValue
+                               ? DateTime.MaxValue : dueDate;
+                       return dueDate;
+               }
+               
+               public string UpdateText (ITaskCore task, string text)
+               {
+                       var dummyTask = backend.GetTaskBy (task.Id);
+                       dummyTask.Text = text;
+                       return text;
+               }
+               
+               public TaskPriority UpdatePriority (
+                       ITaskCore task, TaskPriority priority)
+               {
+                       var dummyTask = backend.GetTaskBy (task.Id);
+                       dummyTask.Priority = (int)priority;
+                       return priority;
+               }
+
+               #region Notes
+
+               public INoteCore UpdateNote (ITaskCore task, INoteCore note)
+               {
+                       throw new NotSupportedException (
+                               "This backend supports multiple notes.");
+               }
+
+               bool INoteCollectionRepo.SupportsSharingItemsWithOtherCollections {
+                       get { return false; }
+               }
+
+               void INoteCollectionRepo.AddNew (ITaskCore task, INoteCore note)
+               {
+                       var dummyTask = backend.GetTaskBy (task.Id);
+                       var dummyNote = new DummyNote (note.Text);
+                       dummyTask.TaskNotes.Add (dummyNote);
+               }
+               
+               void INoteCollectionRepo.Add (ITaskCore task, INoteCore note)
+               {
+                       throw new NotSupportedException (
+                               "Notes can only belong to one task.");
+               }
+               
+               void INoteCollectionRepo.Remove (ITaskCore task, INoteCore note)
+               {
+                       var dummyTask = backend.GetTaskBy (task.Id);
+                       var dummyNote = dummyTask.TaskNotes.Single (
+                               n => n.Id.ToString () == note.Id);
+                       dummyTask.TaskNotes.Remove (dummyNote);
+               }
+               
+               void INoteCollectionRepo.ClearAll (ITaskCore container)
+               {
+                       var dummyTask = backend.GetTaskBy (container.Id);
+                       dummyTask.TaskNotes.Clear ();
+               }
+
+               IEnumerable<INoteCore> INoteCollectionRepo.GetAll (
+                       ITaskCore container)
+               {
+                       var dummyTask = backend.GetTaskBy (container.Id);
+                       foreach (var dummyNote in dummyTask.TaskNotes)
+                               yield return CreateNote (dummyNote);
+               }
+               
+               INoteCore INoteCollectionRepo.GetBy (
+                       ITaskCore container, string id)
+               {
+                       return CreateNote (backend.GetNoteBy (id));
+               }
+
+               #endregion
+
+               #region Nested Tasks
+
+               bool ITaskCollectionRepo.SupportsSharingItemsWithOtherCollections {
+                       get { throw new NotSupportedException (NestedTasksErrMsg); }
+               }
+               
+               void ITaskCollectionRepo.Add (ITaskCore container, ITaskCore item)
+               {
+                       throw new NotSupportedException (NestedTasksErrMsg);
+               }
+               
+               void ITaskCollectionRepo.AddNew (ITaskCore container, ITaskCore item)
+               {
+                       throw new NotSupportedException (NestedTasksErrMsg);
+               }
+               
+               void ITaskCollectionRepo.Remove (ITaskCore container, ITaskCore item)
+               {
+                       throw new NotSupportedException (NestedTasksErrMsg);
+               }
+               
+               void ITaskCollectionRepo.ClearAll (ITaskCore container)
+               {
+                       throw new NotSupportedException (NestedTasksErrMsg);
+               }
+
+               IEnumerable<ITaskCore> ITaskCollectionRepo.GetAll (
+                       ITaskCore container)
+               {
+                       throw new NotSupportedException (NestedTasksErrMsg);
+               }
+               
+               ITaskCore ITaskCollectionRepo.GetBy (
+                       ITaskCore container, string id)
+               {
+                       throw new NotSupportedException (NestedTasksErrMsg);
+               }
+
+               #endregion
+
+               INoteCore CreateNote (DummyNote dummyNote)
+               {
+                       var note = backend.Factory.CreateNote (dummyNote.Id.ToString ());
+                       note.Text = dummyNote.Text;
+                       return note;
+               }
+
+               DummyBackend backend;
+       }
+}
diff --git a/src/libtasque/CategoryComparer.cs b/src/Addins/Backends/Rtm/Extensions.cs
similarity index 57%
copy from src/libtasque/CategoryComparer.cs
copy to src/Addins/Backends/Rtm/Extensions.cs
index b81fcfa..19623a2 100644
--- a/src/libtasque/CategoryComparer.cs
+++ b/src/Addins/Backends/Rtm/Extensions.cs
@@ -1,10 +1,10 @@
 //
-// CategoryComparer.cs
+// Extensions.cs
 //
 // Author:
 //       Antonius Riha <antoniusriha gmail com>
 //
-// Copyright (c) 2012 Antonius Riha
+// Copyright (c) 2013 Antonius Riha
 //
 // Permission is hereby granted, free of charge, to any person obtaining a copy
 // of this software and associated documentation files (the "Software"), to deal
@@ -23,23 +23,45 @@
 // 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.Generic;
+using System;
+using RtmNet;
 
-namespace Tasque
+namespace Tasque.Backends.Rtm
 {
-       public class CategoryComparer : Comparer<ICategory>
+       public static class Extensions
        {
-               public override int Compare (ICategory x, ICategory y)
+               public static TaskPriority GetTaskPriority (this Task source)
                {
-                       if (x == null || y == null)
-                               return 0;
-                       
-                       if (x is AllCategory)
-                               return -1;
-                       else if (y is AllCategory)
-                               return 1;
-                       
-                       return (x.Name.CompareTo (y.Name));
+                       if (source == null)
+                               throw new NullReferenceException ("source");
+
+                       switch (source.Priority) {
+                       case "N":
+                               return TaskPriority.None;
+                       case "1":
+                               return TaskPriority.High;
+                       case "2":
+                               return TaskPriority.Medium;
+                       case "3":
+                               return TaskPriority.Low;
+                       }
+               }
+
+               public static string GetPriorityString (this ITaskCore source)
+               {
+                       if (source == null)
+                               throw new NullReferenceException ("source");
+
+                       switch (source.Priority) {
+                       case TaskPriority.None:
+                               return "N";
+                       case TaskPriority.High:
+                               return "1";
+                       case TaskPriority.Medium:
+                               return "2";
+                       case TaskPriority.Low:
+                               return "3";
+                       }
                }
        }
 }
diff --git a/src/Addins/Backends/Rtm/Gtk/RtmPreferencesWidget.cs 
b/src/Addins/Backends/Rtm/Gtk/RtmPreferencesWidget.cs
index 21b4204..077a175 100644
--- a/src/Addins/Backends/Rtm/Gtk/RtmPreferencesWidget.cs
+++ b/src/Addins/Backends/Rtm/Gtk/RtmPreferencesWidget.cs
@@ -6,7 +6,7 @@ using Mono.Unix;
 using Gdk;
 using Gtk;
 using Tasque;
-using Tasque.Backends;
+using Tasque.Data;
 
 namespace Tasque.Backends.Rtm
 {
diff --git a/src/Addins/Backends/Rtm/Properties/AssemblyInfo.cs 
b/src/Addins/Backends/Rtm/Properties/AssemblyInfo.cs
index e410ed4..79400d3 100644
--- a/src/Addins/Backends/Rtm/Properties/AssemblyInfo.cs
+++ b/src/Addins/Backends/Rtm/Properties/AssemblyInfo.cs
@@ -24,6 +24,9 @@
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 // THE SOFTWARE.
 using System.Reflection;
+using Mono.Addins;
 
 [assembly: AssemblyTitle("RtmBackend")]
 [assembly: AssemblyDescription("Remember the Milk backend for Tasque")]
+[assembly: Addin]
+[assembly: AddinDependency ("libtasque", "0.2.0")]
diff --git a/src/Addins/Backends/Rtm/RtmBackend.cs b/src/Addins/Backends/Rtm/RtmBackend.cs
index bea2612..0a5d27d 100644
--- a/src/Addins/Backends/Rtm/RtmBackend.cs
+++ b/src/Addins/Backends/Rtm/RtmBackend.cs
@@ -4,7 +4,7 @@
 // Author:
 //       Antonius Riha <antoniusriha gmail com>
 //
-// Copyright (c) 2012 Antonius Riha
+// Copyright (c) 2012-2013 Antonius Riha
 //
 // Permission is hereby granted, free of charge, to any person obtaining a copy
 // of this software and associated documentation files (the "Software"), to deal
@@ -25,100 +25,59 @@
 // THE SOFTWARE.
 using System;
 using System.Collections.Generic;
-using System.Collections.ObjectModel;
-using System.ComponentModel;
-using System.Linq;
+using Tasque.Data;
+using Tasque.Utils;
 
 namespace Tasque.Backends.Rtm
 {
-       public class RtmBackend : IBackend
+       [BackendExtension ("Remember the Milk")]
+       public class RtmBackend : IBackend2
        {
-               public RtmBackend ()
-               {
-                       taskComparer = new TaskComparer ();
-                       categoryComparer = new CategoryComparer ();
-
-                       tasks = new ObservableCollection<ITask> ();
-                       categories = new ObservableCollection<ICategory> ();
+               public bool IsConfigured { get; private set; }
 
-                       Tasks = new ReadOnlyObservableCollection<ITask> (tasks);
-                       Categories = new ReadOnlyObservableCollection<ICategory> (categories);
-               }
+               public bool IsInitialized { get; private set; }
 
-               public string Name { get { return "Remember the Milk"; } }
-               
-               public ICollection<ITask> Tasks { get; private set; }
-               
-               public ICollection<ICategory> Categories { get; private set; }
-               
-               public bool Configured { get; private set; }
-               
-               public bool Initialized { get; private set; }
-               
                public IBackendPreferences Preferences {
                        get { return new RtmPreferencesWidget (this, preferences); }
                }
 
-               public ITask CreateTask (string taskName, ICategory category)
+               public TasqueObjectFactory Factory { get; private set; }
+               
+               public RtmNet.Rtm Rtm { get; private set; }
+
+               public RtmTaskListRepository TaskListRepo { get; private set; }
+
+               public string Timeline { get; private set; }
+
+               public IEnumerable<ITaskListCore> GetAll ()
                {
-                       RtmTask rtmTask = null;
+                       yield return allList;
 
-                       string categoryID = null;
-                       if (!(category is AllCategory))
-                               categoryID = (category as RtmCategory).ID;
-                       
-                       if (rtm != null) {
-                               try {
-                                       RtmNet.List list;
-                                       if (categoryID == null)
-                                               list = rtm.TasksAdd (timeline, taskName);
-                                       else
-                                               list = rtm.TasksAdd (timeline, taskName, categoryID);
-                                       rtmTask = UpdateTaskFromResult (list);
-                               } catch (Exception e) {
-                                       Logger.Debug ("Unable to set create task: " + taskName);
-                                       Logger.Debug (e.ToString ());
-                               }
-                       } else
-                               throw new Exception ("Unable to communicate with Remember The Milk");
-                       
-                       return rtmTask;
+                       var lists = Rtm.ListsGetList ();
+                       foreach (var list in lists.listCollection) {
+                               ITaskListCore taskList;
+                               if (list.Smart == 1)
+                                       taskList = Factory.CreateSmartTaskList (list.ID,
+                                                                               list.Name);
+                               else
+                                       taskList = Factory.CreateTaskList (list.ID, list.Name);
+                               yield return taskList;
+                       }
                }
 
-               public void DeleteTask (ITask task)
+               public ITaskListCore GetBy (string id)
                {
-                       var rtmTask = task as RtmTask;
-                       if (rtm != null) {
-                               try {
-                                       rtm.TasksDelete (timeline, rtmTask.ListID,
-                                                        rtmTask.SeriesTaskID, rtmTask.TaskTaskID);
-                                       rtmTask.Delete ();
-                               } catch (Exception e) {
-                                       Logger.Debug ("Unable to delete task: " + task.Name);
-                                       Logger.Debug (e.ToString ());
-                               }
-                       } else
-                               throw new Exception ("Unable to communicate with Remember The Milk");
+                       throw new NotImplementedException ();
                }
 
-               public void Refresh ()
+               public void Create (ITaskListCore taskList)
                {
-                       if (rtmAuth == null)
-                               return;
-
-                       Logger.Debug("Refreshing data...");
-
-                       if (BackendSyncStarted != null)
-                               BackendSyncStarted ();
-
-                       var lists = rtm.ListsGetList ();
-                       UpdateCategories (lists);
-                       UpdateTasks (lists);
-
-                       if (BackendSyncFinished != null)
-                               BackendSyncFinished ();
+                       throw new NotImplementedException ();
+               }
 
-                       Logger.Debug("Done refreshing data!");
+               public void Delete (ITaskListCore taskList)
+               {
+                       throw new NotImplementedException ();
                }
 
                public void Initialize (IPreferences preferences)
@@ -126,11 +85,7 @@ namespace Tasque.Backends.Rtm
                        if (preferences == null)
                                throw new ArgumentNullException ("preferences");
                        this.preferences = preferences;
-                       
-                       // make sure we have the all Category in our list
-                       AllCategory allCategory = new AllCategory (preferences);
-                       AddCategory (allCategory);
-                       
+
                        // *************************************
                        // AUTHENTICATION to Remember The Milk
                        // *************************************
@@ -138,77 +93,58 @@ namespace Tasque.Backends.Rtm
                        if (authToken != null) {
                                Logger.Debug ("Found AuthToken, checking credentials...");
                                try {
-                                       rtm = new RtmNet.Rtm (apiKey, sharedSecret, authToken);
-                                       rtmAuth = rtm.AuthCheckToken (authToken);
-                                       timeline = rtm.TimelineCreate ();
+                                       Rtm = new RtmNet.Rtm (ApiKey, SharedSecret, authToken);
+                                       rtmAuth = Rtm.AuthCheckToken (authToken);
+                                       Timeline = Rtm.TimelineCreate ();
                                        Logger.Debug ("RTM Auth Token is valid!");
                                        Logger.Debug ("Setting configured status to true");
-                                       Configured = true;
+                                       IsConfigured = true;
                                } catch (RtmNet.RtmApiException e) {
                                        preferences.Set (PreferencesKeys.AuthTokenKey, null);
                                        preferences.Set (PreferencesKeys.UserIdKey, null);
                                        preferences.Set (PreferencesKeys.UserNameKey, null);
-                                       rtm = null;
+                                       Rtm = null;
                                        rtmAuth = null;
-                                       Logger.Error ("Exception authenticating, reverting" + e.Message);
+                                       Logger.Error ("Exception authenticating, reverting "
+                                                     + e.Message);
                                } catch (RtmNet.ResponseXmlException e) {
-                                       rtm = null;
+                                       Rtm = null;
                                        rtmAuth = null;
-                                       Logger.Error ("Cannot parse RTM response. Maybe the service is down."
-                                               + e.Message);
+                                       Logger.Error ("Cannot parse RTM response. " +
+                                               "Maybe the service is down. " + e.Message);
                                } catch (RtmNet.RtmWebException e) {
-                                       rtm = null;
+                                       Rtm = null;
                                        rtmAuth = null;
-                                       Logger.Error ("Not connected to RTM, maybe proxy: #{0}", e.Message);
+                                       Logger.Error ("Not connected to RTM, maybe proxy: #{0}",
+                                                     e.Message);
                                } catch (System.Net.WebException e) {
-                                       rtm = null;
+                                       Rtm = null;
                                        rtmAuth = null;
-                                       Logger.Error ("Problem connecting to internet: #{0}", e.Message);
+                                       Logger.Error ("Problem connecting to internet: #{0}",
+                                                     e.Message);
                                }
                        }
-                       
-                       if (rtm == null)
-                               rtm = new RtmNet.Rtm (apiKey, sharedSecret);
-
-                       Refresh ();
 
-                       Initialized = true;
-                       if (BackendInitialized != null)
-                               BackendInitialized ();
-               }
-
-               public void Dispose ()
-               {
-                       if (disposed)
+                       if (Rtm == null) {
+                               Rtm = new RtmNet.Rtm (ApiKey, SharedSecret);
+                               if (NeedsConfiguration != null)
+                                       NeedsConfiguration (this, EventArgs.Empty);
                                return;
+                       }
 
-                       tasks.Clear ();
-                       categories.Clear ();
-
-                       rtm = null;
-                       Initialized = false;
-                       disposed = true;
-               }
-
-               public event BackendInitializedHandler BackendInitialized;
-               public event BackendSyncStartedHandler BackendSyncStarted;
-               public event BackendSyncFinishedHandler BackendSyncFinished;
-
-               #region Internals
-               internal void DeleteTask (RtmTask task)
-               {
-                       if (tasks.Remove (task))
-                               task.PropertyChanged -= HandlePropertyChanged;
+                       FinishInitialization ();
                }
 
-               internal void FinishedAuth ()
+               public void FinishedAuth ()
                {
-                       rtmAuth = rtm.AuthGetToken (frob);
+                       rtmAuth = Rtm.AuthGetToken (frob);
                        if (rtmAuth != null) {
                                preferences.Set (PreferencesKeys.AuthTokenKey, rtmAuth.Token);
                                if (rtmAuth.User != null) {
-                                       preferences.Set (PreferencesKeys.UserNameKey, rtmAuth.User.Username);
-                                       preferences.Set (PreferencesKeys.UserIdKey, rtmAuth.User.UserId);
+                                       preferences.Set (PreferencesKeys.UserNameKey,
+                                                        rtmAuth.User.Username);
+                                       preferences.Set (PreferencesKeys.UserIdKey,
+                                                        rtmAuth.User.UserId);
                                }
                        }
                        
@@ -216,298 +152,97 @@ namespace Tasque.Backends.Rtm
                        if (authToken != null) {
                                Logger.Debug ("Found AuthToken, checking credentials...");
                                try {
-                                       rtm = new RtmNet.Rtm (apiKey, sharedSecret, authToken);
-                                       rtmAuth = rtm.AuthCheckToken (authToken);
-                                       timeline = rtm.TimelineCreate ();
+                                       Rtm = new RtmNet.Rtm (ApiKey, SharedSecret, authToken);
+                                       rtmAuth = Rtm.AuthCheckToken (authToken);
+                                       Timeline = Rtm.TimelineCreate ();
                                        Logger.Debug ("RTM Auth Token is valid!");
                                        Logger.Debug ("Setting configured status to true");
-                                       Configured = true;
-                                       Refresh ();
+                                       IsConfigured = true;
+                                       FinishInitialization ();
                                } catch (Exception e) {
-                                       rtm = null;
+                                       Rtm = null;
                                        rtmAuth = null;                         
-                                       Logger.Error ("Exception authenticating, reverting" + e.Message);
-                               }       
-                       }
-               }
-
-               internal string GetAuthUrl ()
-               {
-                       frob = rtm.AuthGetFrob ();
-                       string url = rtm.AuthCalcUrl (frob, RtmNet.AuthLevel.Delete);
-                       return url;
-               }
-
-               internal RtmCategory GetCategory (string id)
-               {
-                       foreach (var item in categories) {
-                               var category = item as RtmCategory;
-                               if (category != null && category.ID == id)
-                                       return category;
-                       }
-                       return null;
-               }
-
-               internal void UpdateTaskName (RtmTask task)
-               {
-                       if (rtm != null) {
-                               try {
-                                       RtmNet.List list = rtm.TasksSetName (timeline, task.ListID, 
task.SeriesTaskID, task.TaskTaskID, task.Name);             
-                                       UpdateTaskFromResult (list);
-                               } catch (Exception e) {
-                                       Logger.Debug ("Unable to set name on task: " + task.Name);
-                                       Logger.Debug (e.ToString ());
-                               }
-                       }
-               }
-               
-               internal void UpdateTaskDueDate (RtmTask task)
-               {
-                       if (rtm != null) {
-                               try {
-                                       if (task.DueDate == DateTime.MinValue)
-                                               rtm.TasksSetDueDate (timeline, task.ListID, 
task.SeriesTaskID, task.TaskTaskID);
-                                       else
-                                               rtm.TasksSetDueDate (timeline, task.ListID, 
task.SeriesTaskID, task.TaskTaskID, task.DueDateString);
-                               } catch (Exception e) {
-                                       Logger.Debug ("Unable to set due date on task: " + task.Name);
-                                       Logger.Debug (e.ToString ());
+                                       Logger.Error ("Exception authenticating, reverting"
+                                                     + e.Message);
                                }
                        }
                }
                
-               internal void UpdateTaskPriority (RtmTask task)
+               public string GetAuthUrl ()
                {
-                       if (rtm != null) {
-                               try {
-                                       RtmNet.List list = rtm.TasksSetPriority (timeline, task.ListID, 
task.SeriesTaskID, task.TaskTaskID, task.PriorityString);
-                                       UpdateTaskFromResult (list);
-                               } catch (Exception e) {
-                                       Logger.Debug ("Unable to set priority on task: " + task.Name);
-                                       Logger.Debug (e.ToString ());
-                               }
-                       }
-               }
-               
-               internal void UpdateTaskActive (RtmTask task)
-               {
-                       if (task.State == TaskState.Completed) {
-                               if (rtm != null) {
-                                       try {
-                                               rtm.TasksUncomplete (timeline, task.ListID, 
task.SeriesTaskID, task.TaskTaskID);
-                                       } catch (Exception e) {
-                                               Logger.Debug ("Unable to set Task as completed: " + 
task.Name);
-                                               Logger.Debug (e.ToString ());
-                                       }
-                               }
-                       }
-               }
-               
-               internal void UpdateTaskCompleted (RtmTask task)
-               {
-                       if (rtm != null) {
-                               try {
-                                       rtm.TasksComplete (timeline, task.ListID, task.SeriesTaskID, 
task.TaskTaskID);
-                               } catch (Exception e) {
-                                       Logger.Debug ("Unable to set Task as completed: " + task.Name);
-                                       Logger.Debug (e.ToString ());
-                               }
-                       }
-               }
-               
-               internal void MoveTaskCategory (RtmTask task, string id)
-               {
-                       if (rtm != null) {
-                               try {
-                                       rtm.TasksMoveTo (timeline, task.ListID, id, task.SeriesTaskID, 
task.TaskTaskID);
-                               } catch (Exception e) {
-                                       Logger.Debug ("Unable to set Task as completed: " + task.Name);
-                                       Logger.Debug (e.ToString ());
-                               }
-                       }                                       
+                       frob = Rtm.AuthGetFrob ();
+                       string url = Rtm.AuthCalcUrl (frob, RtmNet.AuthLevel.Delete);
+                       return url;
                }
 
-               internal RtmNote CreateNote (RtmTask rtmTask, string text)
+               public string EncodeTaskId (string taskSeriesId, string taskId)
                {
-                       RtmNet.Note note = null;
-                       RtmNote rtmNote = null;
-                       
-                       if (rtm != null) {
-                               try {
-                                       note = rtm.NotesAdd (timeline, rtmTask.ListID, rtmTask.SeriesTaskID, 
rtmTask.TaskTaskID, String.Empty, text);
-                                       rtmNote = new RtmNote (note);
-                               } catch (Exception e) {
-                                       Logger.Debug ("RtmBackend.CreateNote: Unable to create a new note");
-                                       Logger.Debug (e.ToString ());
-                               }
-                       } else
-                               throw new Exception ("Unable to communicate with Remember The Milk");
-                       
-                       return rtmNote;
+                       return taskSeriesId + " " + taskId;
                }
 
-               internal void DeleteNote (RtmTask rtmTask, RtmNote note)
+               public void DecodeTaskId (ITaskCore task, out string taskSeriesId,
+                                         out string taskId)
                {
-                       if (rtm != null) {
-                               try {
-                                       rtm.NotesDelete (timeline, note.ID);
-                               } catch (Exception e) {
-                                       Logger.Debug ("RtmBackend.DeleteNote: Unable to delete note");
-                                       Logger.Debug (e.ToString ());
-                               }
-                       } else
-                               throw new Exception ("Unable to communicate with Remember The Milk");
+                       var ids = task.Id.Split ();
+                       taskSeriesId = ids [0];
+                       taskId = ids [1];
                }
-               
-               internal void SaveNote (RtmTask rtmTask, RtmNote note)
-               {
-                       if (rtm != null) {
-                               try {
-                                       rtm.NotesEdit (timeline, note.ID, String.Empty, note.Text);
-                               } catch (Exception e) {
-                                       Logger.Debug ("RtmBackend.SaveNote: Unable to save note");
-                                       Logger.Debug (e.ToString ());
-                               }
-                       } else
-                               throw new Exception ("Unable to communicate with Remember The Milk");
-               }
-               #endregion
 
-               #region My privates
-               /// <summary>
-               /// Update the model to match what is in RTM
-               /// FIXME: This is a lame implementation and needs to be optimized
-               /// </summary>          
-               void UpdateCategories (RtmNet.Lists lists)
-               {
-                       Logger.Debug ("RtmBackend.UpdateCategories was called");
-                       try {
-                               foreach (var list in lists.listCollection) {
-                                       if (list.Smart == 1) {
-                                               Logger.Warn ("Smart list \"{0}\" omitted", list.Name);
-                                               continue;
-                                       }
-                                       
-                                       var rtmCategory = new RtmCategory (list);
-                                       if (categories.Any (c => c.Name == rtmCategory.Name))
-                                               continue;
-                                       
-                                       AddCategory (rtmCategory);
-                               }
-                       } catch (Exception e) {
-                               Logger.Debug ("Exception in fetch " + e.Message);
-                       }
-                       Logger.Debug ("RtmBackend.UpdateCategories is done");                   
-               }
-               
-               /// <summary>
-               /// Update the model to match what is in RTM
-               /// FIXME: This is a lame implementation and needs to be optimized
-               /// </summary>          
-               void UpdateTasks (RtmNet.Lists lists)
+               public void Dispose ()
                {
-                       Logger.Debug ("RtmBackend.UpdateTasks was called");
-                       try {
-                               foreach (var list in lists.listCollection) {
-                                       // smart lists are based on criteria and therefore
-                                       // can contain tasks that actually belong to another list.
-                                       // Hence skip smart lists in task list population.
-                                       if (list.Smart == 1)
-                                               continue;
-                                       
-                                       RtmNet.Tasks rtmTasks = null;
-                                       try {
-                                               rtmTasks = rtm.TasksGetList (list.ID);
-                                       } catch (Exception tglex) {
-                                               Logger.Debug ("Exception calling TasksGetList (list.ListID) "
-                                                       + tglex.Message);
-                                       }
-                                       
-                                       if (rtmTasks != null) {
-                                               foreach (var tList in rtmTasks.ListCollection) {
-                                                       if (tList.TaskSeriesCollection == null)
-                                                               continue;
+                       if (disposed)
+                               return;
 
-                                                       foreach (var ts in tList.TaskSeriesCollection)
-                                                               UpdateTaskCore (ts, tList.ID);
-                                               }
-                                       }
-                               }
-                       } catch (Exception e) {
-                               Logger.Debug ("Exception in fetch " + e.Message);
-                               Logger.Debug (e.ToString ());
-                       }
-                       Logger.Debug ("RtmBackend.UpdateTasks is done");                        
+                       Rtm = null;
+                       IsInitialized = false;
+                       disposed = true;
                }
 
-               RtmTask UpdateTaskFromResult (RtmNet.List list)
-               {
-                       var ts = list.TaskSeriesCollection [0];
-                       if (ts != null)
-                               return UpdateTaskCore (ts, list.ID);
-                       return null;
-               }
+               public event EventHandler Disposed, Initialized, NeedsConfiguration;
 
-               RtmTask UpdateTaskCore (RtmNet.TaskSeries taskSeries, string listId)
-               {
-                       RtmTask rtmTask = null;
-                       foreach (var task in taskSeries.TaskCollection) {
-                               rtmTask = new RtmTask (taskSeries, task, this, listId);
-                               if (tasks.Any (t => t.Id == rtmTask.Id))
-                                       continue;
-                               
-                               rtmTask.PropertyChanged += HandlePropertyChanged;
-                               AddTask (rtmTask);
-                       }
-                       /* Always return the last task received */
-                       return rtmTask;
+               #region Explicit content
+               INoteRepository IRepositoryProvider<INoteRepository>.Repository {
+                       get { return noteRepo; }
                }
                
-               void AddCategory (ICategory category)
-               {
-                       var index = categories.Count;
-                       var valIdx = categories.Select ((val, idx) => new { val, idx })
-                               .FirstOrDefault (x => categoryComparer.Compare (x.val, category) > 0);
-                       if (valIdx != null)
-                               index = valIdx.idx;
-                       categories.Insert (index, category);
+               ITaskListRepository IRepositoryProvider<ITaskListRepository>
+                       .Repository {
+                       get { return TaskListRepo; }
                }
                
-               void AddTask (RtmTask task)
-               {
-                       var index = tasks.Count;
-                       var valIdx = tasks.Select ((val, idx) => new { val, idx })
-                               .FirstOrDefault (t => taskComparer.Compare (t.val, task) > 0);
-                       if (valIdx != null)
-                               index = valIdx.idx;
-                       
-                       tasks.Insert (index, task);
+               ITaskRepository IRepositoryProvider<ITaskRepository>.Repository {
+                       get { return taskRepo; }
                }
-               
-               void HandlePropertyChanged (object sender, PropertyChangedEventArgs e)
+               #endregion
+
+               void FinishInitialization ()
                {
-                       // when a property changes (any property atm), "reorder" tasks
-                       var task = (RtmTask)sender;
-                       if (tasks.Remove (task))
-                               AddTask (task);
-               }
+                       allList = new AllList (preferences);
 
-               ObservableCollection<ITask> tasks;
-               ObservableCollection<ICategory> categories;
-               TaskComparer taskComparer;
-               CategoryComparer categoryComparer;
+                       TaskListRepo = new RtmTaskListRepository (this);
+                       taskRepo = new RtmTaskRepository (this);
+                       noteRepo = new RtmNoteRepository (this);
+                       
+                       Factory = new TasqueObjectFactory (
+                               TaskListRepo, taskRepo, noteRepo);
+                       
+                       IsInitialized = true;
+                       if (Initialized != null)
+                               Initialized (null, null);
+               }
 
                IPreferences preferences;
+               AllList allList;
 
-               const string apiKey = "b29f7517b6584035d07df3170b80c430";
-               const string sharedSecret = "93eb5f83628b2066";
+               INoteRepository noteRepo;
+               ITaskRepository taskRepo;
+
+               const string ApiKey = "b29f7517b6584035d07df3170b80c430",
+                       SharedSecret = "93eb5f83628b2066";
 
-               RtmNet.Rtm rtm;
                string frob;
                RtmNet.Auth rtmAuth;
-               string timeline;
 
                bool disposed;
-               #endregion
        }
 }
diff --git a/src/Addins/Backends/Rtm/RtmBackend.csproj b/src/Addins/Backends/Rtm/RtmBackend.csproj
index 8373fad..08fc454 100644
--- a/src/Addins/Backends/Rtm/RtmBackend.csproj
+++ b/src/Addins/Backends/Rtm/RtmBackend.csproj
@@ -12,7 +12,7 @@
     <AssemblyName>RtmBackend</AssemblyName>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
-    <ReleaseVersion>0.1.13</ReleaseVersion>
+    <ReleaseVersion>0.2.0</ReleaseVersion>
     <BuildEnabled>$(EnableBackendRtm)</BuildEnabled>
     <PackageName>tasque</PackageName>
     <TopBuildDir>..\..\..\..</TopBuildDir>
@@ -47,18 +47,26 @@
     <Reference Include="System" />
     <Reference Include="gtk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f">
       <Private>False</Private>
+      <Package>gtk-sharp-2.0</Package>
     </Reference>
     <Reference Include="Mono.Posix" />
     <Reference Include="gdk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f">
       <Private>False</Private>
+      <Package>gtk-sharp-2.0</Package>
     </Reference>
     <Reference Include="glib-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f">
       <Private>False</Private>
+      <Package>glib-sharp-2.0</Package>
     </Reference>
     <Reference Include="atk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f">
       <Private>False</Private>
+      <Package>gtk-sharp-2.0</Package>
     </Reference>
     <Reference Include="System.Core" />
+    <Reference Include="Mono.Addins, Version=0.6.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756">
+      <Private>False</Private>
+      <Package>mono-addins</Package>
+    </Reference>
   </ItemGroup>
   <ItemGroup>
     <ProjectReference Include="..\..\..\libtasque\libtasque.csproj">
@@ -71,19 +79,25 @@
     </ProjectReference>
   </ItemGroup>
   <ItemGroup>
-    <Compile Include="RtmTask.cs" />
-    <Compile Include="RtmNote.cs" />
-    <Compile Include="RtmCategory.cs" />
     <Compile Include="RtmBackend.cs" />
     <Compile Include="Gtk\RtmPreferencesWidget.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="..\..\..\..\build\CommonAssemblyInfo.cs">
       <Link>Properties\CommonAssemblyInfo.cs</Link>
     </Compile>
+    <Compile Include="RtmNoteRepository.cs" />
+    <Compile Include="RtmTaskRepository.cs" />
+    <Compile Include="RtmTaskListRepository.cs" />
+    <Compile Include="Extensions.cs" />
   </ItemGroup>
   <ItemGroup>
     <Folder Include="Gtk\" />
     <Folder Include="Properties\" />
   </ItemGroup>
   <Import Project="..\..\..\..\build\X.Common.targets" />
+  <ItemGroup>
+    <None Include="RtmTask.cs" />
+    <None Include="RtmNote.cs" />
+    <None Include="RtmList.cs" />
+  </ItemGroup>
 </Project>
diff --git a/src/Addins/Backends/Rtm/RtmCategory.cs b/src/Addins/Backends/Rtm/RtmList.cs
similarity index 55%
rename from src/Addins/Backends/Rtm/RtmCategory.cs
rename to src/Addins/Backends/Rtm/RtmList.cs
index b8cac95..d688f1b 100644
--- a/src/Addins/Backends/Rtm/RtmCategory.cs
+++ b/src/Addins/Backends/Rtm/RtmList.cs
@@ -8,24 +8,25 @@ using RtmNet;
 
 namespace Tasque.Backends.Rtm
 {
-       public class RtmCategory : ICategory
+       public class RtmList : TaskList
        {
-               private List list;
-
-               public RtmCategory(List list)
+               public RtmList (RtmBackend backend, List list)
                {
+                       if (backend == null)
+                               throw new System.ArgumentNullException ("backend");
+                       if (list == null)
+                               throw new System.ArgumentNullException ("list");
+                       this.backend = backend;
                        this.list = list;
-               }
-               
-               public string Name
-               {
-                       get { return list.Name; }
+                       Name = list.Name;
                }
 
                public string ID
                {
                        get { return list.ID; }
                }
+
+               public override bool IsReadOnly { get { return false; } }
     
                public int Deleted
                {
@@ -52,13 +53,13 @@ namespace Tasque.Backends.Rtm
                        get { return list.Smart; }
                }
 
-               public bool ContainsTask(ITask task)
+               protected override void OnAdded (Task newTask)
                {
-                       if(task.Category is RtmCategory)
-                               return ((task.Category as RtmCategory).ID.CompareTo(ID) == 0);
-                       else
-                               return false;
+                       backend.MoveTaskTaskList ((RtmTask)newTask, ID);
+                       base.OnAdded (newTask);
                }
 
+               RtmBackend backend;
+               List list;
        }
 }
diff --git a/src/Addins/Backends/Rtm/RtmNote.cs b/src/Addins/Backends/Rtm/RtmNote.cs
index 2e605b5..17146d2 100644
--- a/src/Addins/Backends/Rtm/RtmNote.cs
+++ b/src/Addins/Backends/Rtm/RtmNote.cs
@@ -12,9 +12,9 @@ namespace Tasque.Backends.Rtm
 {
        public class RtmNote : INote
        {
-               Note note;
-               
-               public RtmNote(Note note)
+               RtmNet.Note note;
+
+               public RtmNote(RtmNet.Note note)
                {
                        this.note = note;
                        if( (note.Title != null) && (note.Title.Length > 0) ) {
diff --git a/src/libtasque/CategoryComparer.cs b/src/Addins/Backends/Rtm/RtmNoteRepository.cs
similarity index 51%
copy from src/libtasque/CategoryComparer.cs
copy to src/Addins/Backends/Rtm/RtmNoteRepository.cs
index b81fcfa..879dce1 100644
--- a/src/libtasque/CategoryComparer.cs
+++ b/src/Addins/Backends/Rtm/RtmNoteRepository.cs
@@ -1,10 +1,10 @@
 //
-// CategoryComparer.cs
+// RtmNoteRepository.cs
 //
 // Author:
 //       Antonius Riha <antoniusriha gmail com>
 //
-// Copyright (c) 2012 Antonius Riha
+// Copyright (c) 2013 Antonius Riha
 //
 // Permission is hereby granted, free of charge, to any person obtaining a copy
 // of this software and associated documentation files (the "Software"), to deal
@@ -23,23 +23,49 @@
 // 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.Generic;
+using System;
+using Tasque.Data;
 
-namespace Tasque
+namespace Tasque.Backends.Rtm
 {
-       public class CategoryComparer : Comparer<ICategory>
+       public class RtmNoteRepository : INoteRepository
        {
-               public override int Compare (ICategory x, ICategory y)
+               public RtmNoteRepository (RtmBackend backend)
                {
-                       if (x == null || y == null)
-                               return 0;
-                       
-                       if (x is AllCategory)
-                               return -1;
-                       else if (y is AllCategory)
-                               return 1;
-                       
-                       return (x.Name.CompareTo (y.Name));
+                       if (backend == null)
+                               throw new ArgumentNullException ("backend");
+                       this.backend = backend;
                }
+
+               public string UpdateTitle (INoteCore note, string title)
+               {
+                       throw new NotImplementedException ();
+               }
+
+               string INoteRepository.UpdateText (INoteCore note, string text)
+               {
+
+               }
+
+               void UpdateNote (INoteCore note, string title, string text)
+               {
+                       var rtmNote = backend.Rtm.NotesEdit (backend.Timeline, note.Id, note.Title, 
note.Text);
+                       note.Title =
+               }
+
+               internal void SaveNote (RtmTask rtmTask, RtmNote note)
+               {
+                       if (rtm != null) {
+                               try {
+                                       rtm.NotesEdit (timeline, note.ID, String.Empty, note.Text);
+                               } catch (Exception e) {
+                                       Logger.Debug ("RtmBackend.SaveNote: Unable to save note");
+                                       Logger.Debug (e.ToString ());
+                               }
+                       } else
+                               throw new Exception ("Unable to communicate with Remember The Milk");
+               }
+
+               RtmBackend backend;
        }
 }
diff --git a/src/Addins/Backends/Rtm/RtmTask.cs b/src/Addins/Backends/Rtm/RtmTask.cs
index 1282bdd..61e1ef5 100644
--- a/src/Addins/Backends/Rtm/RtmTask.cs
+++ b/src/Addins/Backends/Rtm/RtmTask.cs
@@ -10,9 +10,8 @@ namespace Tasque.Backends.Rtm
        public class RtmTask : Task
        {
                private RtmBackend rtmBackend;
-               private TaskState state;
-               private RtmCategory category;
-               private List<INote> notes;              
+               private RtmList list;
+               private List<INote> notes;
 
                TaskSeries taskSeries;
                RtmNet.Task task;
@@ -27,17 +26,22 @@ namespace Tasque.Backends.Rtm
                {
                        this.taskSeries = taskSeries;
                        this.rtmBackend = be;
-                       this.category = be.GetCategory(listID);
+                       this.list = be.GetTaskList(listID);
                        this.task = task;
 
-                       if(CompletionDate == DateTime.MinValue )
-                               state = TaskState.Active;
+                       Id = task.TaskID;
+                       Name = taskSeries.Name;
+                       DueDate = task.Due;
+                       CompletionDate = task.Completed;
+                       if (CompletionDate == DateTime.MinValue)
+                               State = TaskState.Active;
                        else
-                               state = TaskState.Completed;
+                               State = TaskState.Completed;
+                       Priority = GetPriority ();
                        notes = new List<INote>();
 
                        if (taskSeries.Notes.NoteCollection != null) {
-                               foreach(Note note in taskSeries.Notes.NoteCollection) {
+                               foreach(var note in taskSeries.Notes.NoteCollection) {
                                        RtmNote rtmNote = new RtmNote(note);
                                        notes.Add(rtmNote);
                                }
@@ -45,44 +49,20 @@ namespace Tasque.Backends.Rtm
                }
                
                #region Public Properties
-               /// <value>
-               /// Gets the id of the task
-               /// </value>
-               public override string Id
-               {
-                       get { return task.TaskID; }
-               }
 
-               /// <value>
-               /// Holds the name of the task
-               /// </value>            
-               public override string Name
+               protected override void OnNameChanged ()
                {
-                       get { return taskSeries.Name; }
-                       set {
-                               if (value != null) {
-                                       OnPropertyChanging ("Name");
-                                       taskSeries.Name = value.Trim ();
-                                       rtmBackend.UpdateTaskName(this);
-                                       OnPropertyChanged ("CompletionDate");
-                               }
-                       }
+                       taskSeries.Name = Name;
+                       rtmBackend.UpdateTaskName (this);
+                       base.OnNameChanged ();
                }
-               
-               /// <value>
-               /// Due Date for the task
-               /// </value>
-               public override DateTime DueDate
+
+               protected override void OnDueDateChanged ()
                {
-                       get { return task.Due; }
-                       set {
-                               OnPropertyChanging ("DueDate");
-                               task.Due = value;
-                               rtmBackend.UpdateTaskDueDate(this);
-                               OnPropertyChanged ("CompletionDate");
-                       }
+                       task.Due = DueDate;
+                       rtmBackend.UpdateTaskDueDate (this);
+                       base.OnDueDateChanged ();
                }
-               
 
                /// <value>
                /// Due Date for the task
@@ -97,113 +77,43 @@ namespace Tasque.Backends.Rtm
                        }
                }
 
-               
-               /// <value>
-               /// Completion Date for the task
-               /// </value>
-               public override DateTime CompletionDate
+               protected override void OnCompletionDateChanged ()
                {
-                       get { return task.Completed; }
-                       set {
-                               OnPropertyChanging ("CompletionDate");
-                               task.Completed = value;
-                               OnPropertyChanged ("CompletionDate");
-                       }
+                       task.Completed = CompletionDate;
+                       base.OnCompletionDateChanged ();
                }
-               
-               /// <value>
-               /// Returns if the task is complete
-               /// </value>
-               public override bool IsComplete
-               {
-                       get { return state == TaskState.Completed; }
-               }
-               
-               /// <value>
-               /// Holds the priority of the task
-               /// </value>
-               public override TaskPriority Priority
-               {
-                       get { 
-                               switch (task.Priority) {
-                                       default:
-                                       case "N":
-                                               return TaskPriority.None;
-                                       case "1":
-                                               return TaskPriority.High;
-                                       case "2":
-                                               return TaskPriority.Medium;
-                                       case "3":
-                                               return TaskPriority.Low;
-                               }
-                       }
-                       set {
-                               OnPropertyChanging ("Priority");
-                               switch (value) {
-                                       default:
-                                       case TaskPriority.None:
-                                               task.Priority = "N";
-                                               break;
-                                       case TaskPriority.High:
-                                               task.Priority = "1";
-                                               break;
-                                       case TaskPriority.Medium:
-                                               task.Priority = "2";
-                                               break;
-                                       case TaskPriority.Low:
-                                               task.Priority = "3";
-                                               break;
-                               }
-                               rtmBackend.UpdateTaskPriority(this);
-                               OnPropertyChanged ("CompletionDate");
+
+               protected override void OnPriorityChanged ()
+               {
+                       switch (Priority) {
+                       default:
+                       case TaskPriority.None:
+                               task.Priority = "N";
+                               break;
+                       case TaskPriority.High:
+                               task.Priority = "1";
+                               break;
+                       case TaskPriority.Medium:
+                               task.Priority = "2";
+                               break;
+                       case TaskPriority.Low:
+                               task.Priority = "3";
+                               break;
                        }
+                       rtmBackend.UpdateTaskPriority (this);
+                       base.OnPriorityChanged ();
                }
                
                public string PriorityString
                {
                        get { return task.Priority; }
-               }               
-               
-               
-               /// <value>
-               /// Returns if the task has any notes
-               /// </value>
-               public override bool HasNotes
-               {
-                       get { return (notes.Count > 0); }
                }
-               
-               /// <value>
-               /// Returns if the task supports multiple notes
-               /// </value>
-               public override NoteSupport NoteSupport
-               {
+
+               public override NoteSupport NoteSupport {
                        get { return NoteSupport.Multiple; }
                }
                
                /// <value>
-               /// Holds the current state of the task
-               /// </value>
-               public override TaskState State
-               {
-                       get { return state; }
-               }
-               
-               /// <value>
-               /// Returns the category object for this task
-               /// </value>
-               public override ICategory Category
-               {
-                       get { return category; } 
-                       set {
-                               OnPropertyChanging ("Category");
-                               RtmCategory rtmCategory = value as RtmCategory;
-                               rtmBackend.MoveTaskCategory(this, rtmCategory.ID);
-                               OnPropertyChanged ("CompletionDate");
-                       }
-               }
-               
-               /// <value>
                /// Returns the notes associates with this task
                /// </value>
                public override List<INote> Notes
@@ -236,39 +146,27 @@ namespace Tasque.Backends.Rtm
                
                public string ListID
                {
-                       get { return category.ID; }
+                       get { return list.ID; }
                }
                #endregion // Public Properties
                
                #region Public Methods
-               /// <summary>
-               /// Activates the task
-               /// </summary>
-               public override void Activate ()
+               protected override void OnActivated ()
                {
-                       Logger.Debug("Activating Task: " + Name);
-                       SetState (TaskState.Active);
-                       CompletionDate = DateTime.MinValue;
+                       rtmBackend.UpdateTaskActive (this);
+                       base.OnActivated ();
                }
-               
-               /// <summary>
-               /// Completes the task
-               /// </summary>
-               public override void Complete ()
+
+               protected override void OnCompleted ()
                {
-                       Logger.Debug("Completing Task: " + Name);
-                       SetState (TaskState.Completed);
-                       if(CompletionDate == DateTime.MinValue)
-                               CompletionDate = DateTime.Now;
+                       rtmBackend.UpdateTaskCompleted (this);
+                       base.OnCompleted ();
                }
-               
-               /// <summary>
-               /// Deletes the task
-               /// </summary>
-               public override void Delete ()
+
+               protected override void OnDeleted ()
                {
-                       SetState (TaskState.Deleted);
                        rtmBackend.DeleteTask (this);
+                       base.OnDeleted ();
                }
                
                /// <summary>
@@ -315,17 +213,23 @@ namespace Tasque.Backends.Rtm
                public override void SaveNote(INote note)
                {               
                        rtmBackend.SaveNote(this, (note as RtmNote));
-               }               
-
-               #endregion // Public Methods
+               }
 
-               void SetState (TaskState value)
-               {
-                       if (value == state)
-                               return;
-                       OnPropertyChanging ("State");
-                       state = value;
-                       OnPropertyChanged ("State");
+               TaskPriority GetPriority ()
+               {
+                       switch (task.Priority) {
+                       default:
+                       case "N":
+                               return TaskPriority.None;
+                       case "1":
+                               return TaskPriority.High;
+                       case "2":
+                               return TaskPriority.Medium;
+                       case "3":
+                               return TaskPriority.Low;
+                       }
                }
+
+               #endregion // Public Methods
        }
 }
diff --git a/src/Addins/Backends/Rtm/RtmTaskListRepository.cs 
b/src/Addins/Backends/Rtm/RtmTaskListRepository.cs
new file mode 100644
index 0000000..f90972e
--- /dev/null
+++ b/src/Addins/Backends/Rtm/RtmTaskListRepository.cs
@@ -0,0 +1,156 @@
+//
+// RtmTaskListRepository.cs
+//
+// Author:
+//       Antonius Riha <antoniusriha gmail com>
+//
+// Copyright (c) 2013 Antonius Riha
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using Tasque.Data;
+using RtmNet;
+
+namespace Tasque.Backends.Rtm
+{
+       using ITaskListTaskCollectionRepo =
+               ICollectionRepository<ITaskCore, ITaskListCore>;
+       
+       public class RtmTaskListRepository : ITaskListRepository
+       {
+               public RtmTaskListRepository (RtmBackend backend)
+               {
+                       if (backend == null)
+                               throw new ArgumentNullException ("backend");
+                       this.backend = backend;
+
+                       Notes = new Collection<Tuple<string, INoteCore>> ();
+               }
+
+               /// <summary>
+               /// Gets the task id - Note tuples.
+               /// </summary>
+               /// <value>
+               /// Task ids and resp. notes.
+               /// </value>
+               public ICollection<Tuple<string, INoteCore>> Notes { get; private set; }
+
+               bool ITaskListRepository.CanChangeName (ITaskListCore taskList)
+               {
+                       return false;
+               }
+
+               string ITaskListRepository.UpdateName (ITaskListCore taskList,
+                                                      string name)
+               {
+                       throw new NotSupportedException (
+                               "Cannot change the name of a task list.");
+               }
+
+               IEnumerable<ITaskCore> ITaskListTaskCollectionRepo.GetAll (
+                       ITaskListCore container)
+               {
+                       var tasks = backend.Rtm.TasksGetList (container.Id);
+                       foreach (var rtmList in tasks.ListCollection) {
+                               if (rtmList.TaskSeriesCollection == null)
+                                       continue;
+                               foreach (var rtmTaskSeries in rtmList.TaskSeriesCollection) {
+                                       var last = rtmTaskSeries.TaskCollection.Length - 1;
+                                       var rtmTask = rtmTaskSeries.TaskCollection [last];
+                                       var taskId = backend.EncodeTaskId (rtmTaskSeries.TaskID,
+                                                                          rtmTask.TaskID);
+                                       ITaskCore task;
+                                       if (rtmTask.Completed == DateTime.MinValue) {
+                                               task = backend.Factory.CreateCompletedTask (
+                                                       taskId, rtmTaskSeries.Name, rtmTask.Completed);
+                                       } else {
+                                               task = backend.Factory.CreateTask (
+                                                       taskId, rtmTaskSeries.Name);
+                                       }
+                                       task.DueDate = rtmTask.Due;
+                                       task.Priority = rtmTask.GetTaskPriority ();
+
+                                       CacheNotes (rtmTaskSeries);
+                               }
+                       }
+               }
+
+               ITaskCore ITaskListTaskCollectionRepo.GetBy (ITaskListCore container,
+                                                            string id)
+               {
+                       throw new NotImplementedException ();
+               }
+
+               void ITaskListTaskCollectionRepo.Add (ITaskListCore container,
+                                                     ITaskCore item)
+               {
+                       throw new NotSupportedException (
+                               "A task can only have one task list.");
+               }
+
+               void ITaskListTaskCollectionRepo.AddNew (ITaskListCore container,
+                                                        ITaskCore item)
+               {
+                       var list = backend.Rtm.TasksAdd (
+                               backend.Timeline, item.Text, container.Id);
+                       var taskSeries = list.TaskSeriesCollection [0];
+                       var last = taskSeries.TaskCollection.Length - 1;
+                       var id = backend.EncodeTaskId (
+                               taskSeries.TaskID, taskSeries.TaskCollection [last].TaskID);
+                       item.SetId (id);
+               }
+
+               void ITaskListTaskCollectionRepo.Remove (ITaskListCore container,
+                                                        ITaskCore item)
+               {
+                       string taskSeriesId, taskId;
+                       backend.DecodeTaskId (item.Id, out taskSeriesId, out taskId);
+                       backend.Rtm.TasksDelete (backend.Timeline, container.Id,
+                                                taskSeriesId, taskId);
+               }
+
+               void ITaskListTaskCollectionRepo.ClearAll (ITaskListCore container)
+               {
+                       throw new NotImplementedException ();
+               }
+
+               void CacheNotes (TaskSeries rtmTaskSeries)
+               {
+                       foreach (var rtmNote in rtmTaskSeries.Notes.NoteCollection) {
+                               var noteTuple = Notes.SingleOrDefault (
+                                       t => t.Item2.Id == rtmNote.ID);
+                               INoteCore note;
+                               if (noteTuple != null)
+                                       note = noteTuple.Item2;
+                               else {
+                                       note = backend.Factory.CreateNote (rtmNote.ID);
+                                       Notes.Add (new Tuple<string, INoteCore> (
+                                               rtmTaskSeries.TaskID, note));
+                               }
+                               note.Title = rtmNote.Title;
+                               note.Text = rtmNote.Text;
+                       }
+               }
+
+               RtmBackend backend;
+       }
+}
diff --git a/src/Addins/Backends/Rtm/RtmTaskRepository.cs b/src/Addins/Backends/Rtm/RtmTaskRepository.cs
new file mode 100644
index 0000000..167e3b1
--- /dev/null
+++ b/src/Addins/Backends/Rtm/RtmTaskRepository.cs
@@ -0,0 +1,216 @@
+//
+// RtmTaskRepository.cs
+//
+// Author:
+//       Antonius Riha <antoniusriha gmail com>
+//
+// Copyright (c) 2013 Antonius Riha
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Tasque.Data;
+using RtmNet;
+
+namespace Tasque.Backends.Rtm
+{
+       using INoteCollectionRepo = ICollectionRepository<INoteCore, ITaskCore>;
+       using ITaskTaskCollectionRepo =
+               ICollectionRepository<ITaskCore, ITaskCore>;
+
+       public class RtmTaskRepository : ITaskRepository
+       {
+               const string NestedTasksErrMsg = "Nested tasks are not supported.";
+               
+               public RtmTaskRepository (RtmBackend backend)
+               {
+                       if (backend == null)
+                               throw new ArgumentNullException ("backend");
+                       this.backend = backend;
+               }
+               
+               bool ITaskRepository.SupportsNestedTasks { get { return false; } }
+               
+               bool ITaskRepository.SupportsDiscarding { get { return false; } }
+               
+               NoteSupport ITaskRepository.NoteSupport {
+                       get { return NoteSupport.Multiple; }
+               }
+               
+               DateTime ITaskRepository.UpdateDueDate (ITaskCore task, DateTime date)
+               {
+                       var taskList = task.TaskListContainers.First ();
+                       string taskSeriesId, taskId;
+                       backend.DecodeTaskId (task, out taskSeriesId, out taskId);
+                       List list;
+                       if (task.DueDate == DateTime.MinValue) {
+                               list = backend.Rtm.TasksSetDueDate (
+                                       backend.Timeline, taskList.Id, taskSeriesId, taskId);
+                       } else {
+                               var format = "yyyy-MM-ddTHH:mm:ssZ";
+                               var dateString = date.ToUniversalTime ().ToString (format);
+                               list = backend.Rtm.TasksSetDueDate (backend.Timeline,
+                                       taskList.Id, taskSeriesId, taskId, dateString);
+                       }
+                       var last = list.TaskSeriesCollection [0].TaskCollection.Length - 1;
+                       return list.TaskSeriesCollection [0].TaskCollection [last].Due;
+               }
+               
+               string ITaskRepository.UpdateText (ITaskCore task, string text)
+               {
+                       var taskList = task.TaskListContainers.First ();
+                       string taskSeriesId, taskId;
+                       backend.DecodeTaskId (task, out taskSeriesId, out taskId);
+                       var list = backend.Rtm.TasksSetName (backend.Timeline,
+                               taskList.Id, taskSeriesId, taskId, task.Text);
+                       return list.TaskSeriesCollection [0].Name;
+               }
+               
+               TaskPriority ITaskRepository.UpdatePriority (ITaskCore task,
+                                                            TaskPriority priority)
+               {
+                       var taskList = task.TaskListContainers.First ();
+                       string taskSeriesId, taskId;
+                       backend.DecodeTaskId (task, out taskSeriesId, out taskId);
+                       var list = backend.Rtm.TasksSetPriority (backend.Timeline,
+                               taskList.Id, taskSeriesId, taskId, task.GetPriorityString ());
+                       var last = list.TaskSeriesCollection [0].TaskCollection.Length - 1;
+                       return list.TaskSeriesCollection [0]
+                               .TaskCollection [last].GetTaskPriority ();
+               }
+               
+               void ITaskRepository.Activate (ITaskCore task)
+               {
+                       var taskList = task.TaskListContainers.First ();
+                       string taskSeriesId, taskId;
+                       backend.DecodeTaskId (task, out taskSeriesId, out taskId);
+                       backend.Rtm.TasksUncomplete (backend.Timeline, taskList.Id,
+                                                    taskSeriesId, taskId);
+               }
+               
+               DateTime ITaskRepository.Complete (ITaskCore task,
+                                                  DateTime completionDate)
+               {
+                       var taskList = task.TaskListContainers.First ();
+                       string taskSeriesId, taskId;
+                       backend.DecodeTaskId (task, out taskSeriesId, out taskId);
+                       backend.Rtm.TasksComplete (backend.Timeline, taskList.Id,
+                                                  taskSeriesId, taskId);
+               }
+               
+               void ITaskRepository.Discard (ITaskCore task)
+               {
+                       throw new NotSupportedException ("Discarding is not supported");
+               }
+
+               #region Notes
+
+               INoteCore ITaskRepository.UpdateNote (ITaskCore task, INoteCore note)
+               {
+                       throw new NotSupportedException (
+                               "This backend supports multiple notes.");
+               }
+               
+               IEnumerable<INoteCore> INoteCollectionRepo.GetAll (ITaskCore container)
+               {
+                       var notes = backend.TaskListRepo.Notes;
+                       return notes.Where (t => t.Item1 == container.Id)
+                                   .Select (t => t.Item2);
+               }
+               
+               INoteCore INoteCollectionRepo.GetBy (ITaskCore container, string id)
+               {
+                       throw new NotImplementedException ();
+               }
+               
+               void INoteCollectionRepo.Add (ITaskCore container, INoteCore item)
+               {
+                       throw new NotSupportedException (
+                               "A note can only belong to a single task.");
+               }
+               
+               void INoteCollectionRepo.AddNew (ITaskCore container, INoteCore item)
+               {
+                       var taskList = container.TaskListContainers.First ();
+                       string taskSeriesId, taskId;
+                       backend.DecodeTaskId (container, out taskSeriesId, out taskId);
+                       var note = backend.Rtm.NotesAdd (backend.Timeline, taskList.Id,
+                               taskSeriesId, taskId, item.Title, item.Text);
+                       item.Text = note.Text;
+                       item.Title = note.Title;
+                       item.SetId (note.ID);
+               }
+               
+               void INoteCollectionRepo.Remove (ITaskCore container, INoteCore item)
+               {
+                       var taskList = container.TaskListContainers.First ();
+                       string taskSeriesId, taskId;
+                       backend.DecodeTaskId (container, out taskSeriesId, out taskId);
+                       backend.Rtm.NotesDelete (backend.Timeline, item.Id);
+               }
+               
+               void INoteCollectionRepo.ClearAll (ITaskCore container)
+               {
+                       throw new NotImplementedException ();
+               }
+
+               #endregion
+
+               #region Nested tasks
+
+               IEnumerable<ITaskCore> ITaskTaskCollectionRepo.GetAll (
+                       ITaskCore container)
+               {
+                       throw new NotSupportedException (NestedTasksErrMsg);
+               }
+
+               ITaskCore ITaskTaskCollectionRepo.GetBy (ITaskCore container,
+                                                        string id)
+               {
+                       throw new NotSupportedException (NestedTasksErrMsg);
+               }
+
+               void ITaskTaskCollectionRepo.Add (ITaskCore container, ITaskCore item)
+               {
+                       throw new NotSupportedException (NestedTasksErrMsg);
+               }
+
+               void ITaskTaskCollectionRepo.AddNew (ITaskCore container,
+                                                    ITaskCore item)
+               {
+                       throw new NotSupportedException (NestedTasksErrMsg);
+               }
+
+               void ITaskTaskCollectionRepo.Remove (ITaskCore container,
+                                                    ITaskCore item)
+               {
+                       throw new NotSupportedException (NestedTasksErrMsg);
+               }
+
+               void ITaskTaskCollectionRepo.ClearAll (ITaskCore container)
+               {
+                       throw new NotSupportedException (NestedTasksErrMsg);
+               }
+
+               #endregion
+
+               RtmBackend backend;
+       }
+}
diff --git a/src/Addins/Backends/Sqlite/SqliteBackend.cs b/src/Addins/Backends/Sqlite/SqliteBackend.cs
index ea3ac97..23bbb82 100644
--- a/src/Addins/Backends/Sqlite/SqliteBackend.cs
+++ b/src/Addins/Backends/Sqlite/SqliteBackend.cs
@@ -16,34 +16,34 @@ namespace Tasque.Backends.Sqlite
                private bool initialized;
                private bool configured = true;
 
-               ObservableCollection<ITask> taskStore;
-               ObservableCollection<ICategory> categoryListStore;
-               ReadOnlyObservableCollection<ITask> readOnlyTaskStore;
-               ReadOnlyObservableCollection<ICategory> readOnlyCategoryStore;
+               ObservableCollection<Task> taskStore;
+               ObservableCollection<TaskList> taskListListStore;
+               ReadOnlyObservableCollection<Task> readOnlyTaskStore;
+               ReadOnlyObservableCollection<TaskList> readOnlyTaskListStore;
                
                TaskComparer taskComparer;
-               CategoryComparer categoryComparer;
+               TaskListComparer taskListComparer;
                
                private Database db;
 
-               public event BackendInitializedHandler BackendInitialized;
-               public event BackendSyncStartedHandler BackendSyncStarted;
-               public event BackendSyncFinishedHandler BackendSyncFinished;
+               public event EventHandler BackendInitialized;
+               public event EventHandler BackendSyncStarted;
+               public event EventHandler BackendSyncFinished;
                
-               SqliteCategory defaultCategory;
-               //SqliteCategory workCategory;
-               //SqliteCategory projectsCategory;
+               SqliteList defaultTaskList;
+               //SqliteTaskList workTaskList;
+               //SqliteTaskList projectsTaskList;
                
                public SqliteBackend ()
                {
                        initialized = false;
-                       taskStore = new ObservableCollection<ITask> ();
-                       categoryListStore = new ObservableCollection<ICategory> ();
-                       readOnlyTaskStore = new ReadOnlyObservableCollection<ITask> (taskStore);
-                       readOnlyCategoryStore
-                               = new ReadOnlyObservableCollection<ICategory> (categoryListStore);
+                       taskStore = new ObservableCollection<Task> ();
+                       taskListListStore = new ObservableCollection<TaskList> ();
+                       readOnlyTaskStore = new ReadOnlyObservableCollection<Task> (taskStore);
+                       readOnlyTaskListStore
+                               = new ReadOnlyObservableCollection<TaskList> (taskListListStore);
                        taskComparer = new TaskComparer ();
-                       categoryComparer = new CategoryComparer ();
+                       taskListComparer = new TaskListComparer ();
                }
                
                #region Public Properties
@@ -55,17 +55,17 @@ namespace Tasque.Backends.Sqlite
                /// <value>
                /// All the tasks including ITaskDivider items.
                /// </value>
-               public ICollection<ITask> Tasks
+               public ICollection<Task> Tasks
                {
                        get { return readOnlyTaskStore; }
                }
                
                /// <value>
-               /// This returns all the task lists (categories) that exist.
+               /// This returns all the task lists (taskLists) that exist.
                /// </value>
-               public ICollection<ICategory> Categories
+               public ICollection<TaskList> TaskLists
                {
-                       get { return readOnlyCategoryStore; }
+                       get { return readOnlyTaskListStore; }
                }
                
                /// <value>
@@ -100,16 +100,16 @@ namespace Tasque.Backends.Sqlite
                #endregion // Public Properties
                
                #region Public Methods
-               public ITask CreateTask (string taskName, ICategory category)           
+               public Task CreateTask (string taskName, TaskList taskList)
                {
-                       // not sure what to do here with the category
+                       // not sure what to do here with the taskList
                        SqliteTask task = new SqliteTask (this, taskName);
                        
-                       // Determine and set the task category
-                       if (category == null || category is Tasque.AllCategory)
-                               task.Category = defaultCategory; // Default to work
+                       // Determine and set the task taskList
+                       if (taskList == null || taskList is Tasque.AllList)
+                               defaultTaskList.Add (task); // Default to work
                        else
-                               task.Category = category;
+                               taskList.Add (task);
                        
                        AddTask (task);
                        task.PropertyChanged += HandlePropertyChanged;
@@ -117,7 +117,7 @@ namespace Tasque.Backends.Sqlite
                        return task;
                }
                
-               public void DeleteTask(ITask task)
+               public void DeleteTask(Task task)
                {
                        //string id = task.Id;
                        task.Delete ();
@@ -139,18 +139,18 @@ namespace Tasque.Backends.Sqlite
                        db.Open();
                        
                        //
-                       // Add in the "All" Category
+                       // Add in the "All" TaskList
                        //
-                       AllCategory allCategory = new Tasque.AllCategory (preferences);
-                       AddCategory (allCategory);
+                       var allList = new AllList (this, preferences);
+                       AddTaskList (allList);
 
-                       RefreshCategories();
-                       RefreshTasks();         
+                       RefreshTaskLists();
+                       RefreshTasks();
 
                        initialized = true;
                        if(BackendInitialized != null) {
-                               BackendInitialized();
-                       }               
+                               BackendInitialized(null, null);
+                       }
                }
 
                public void Dispose()
@@ -158,7 +158,7 @@ namespace Tasque.Backends.Sqlite
                        if (disposed)
                                return;
 
-                       this.categoryListStore.Clear();
+                       this.taskListListStore.Clear();
                        this.taskStore.Clear();
 
                        if (db != null)
@@ -179,23 +179,24 @@ namespace Tasque.Backends.Sqlite
                }
                
                #endregion // Public Methods
-               public void RefreshCategories()
+               public void RefreshTaskLists()
                {
-                       SqliteCategory newCategory;
+                       SqliteList newTaskList;
                        bool hasValues = false;
                        
-                       string command = "SELECT id FROM Categories";
+                       string command = "SELECT id, name FROM Categories";
                        SqliteCommand cmd = db.Connection.CreateCommand();
                        cmd.CommandText = command;
                        SqliteDataReader dataReader = cmd.ExecuteReader();
                        while(dataReader.Read()) {
                            int id = dataReader.GetInt32(0);
+                               var name = dataReader.GetString (1);
                                hasValues = true;
                                
-                               newCategory = new SqliteCategory (this, id);
-                               if( (defaultCategory == null) || (newCategory.Name.CompareTo("Work") == 0) )
-                                       defaultCategory = newCategory;
-                               AddCategory (newCategory);
+                               newTaskList = new SqliteList (this, id, name);
+                               if( (defaultTaskList == null) || (newTaskList.Name.CompareTo("Work") == 0) )
+                                       defaultTaskList = newTaskList;
+                               AddTaskList (newTaskList);
                        }
                        
                        dataReader.Close();
@@ -203,17 +204,17 @@ namespace Tasque.Backends.Sqlite
 
                        if(!hasValues)
                        {
-                               defaultCategory = newCategory = new SqliteCategory (this, "Work");
-                               AddCategory (defaultCategory);
+                               defaultTaskList = newTaskList = new SqliteList (this, "Work");
+                               AddTaskList (defaultTaskList);
 
-                               newCategory = new SqliteCategory (this, "Personal");
-                               AddCategory (newCategory);
+                               newTaskList = new SqliteList (this, "Personal");
+                               AddTaskList (newTaskList);
                                
-                               newCategory = new SqliteCategory (this, "Family");
-                               AddCategory (newCategory);
+                               newTaskList = new SqliteList (this, "Family");
+                               AddTaskList (newTaskList);
 
-                               newCategory = new SqliteCategory (this, "Project");
-                               AddCategory (newCategory);
+                               newTaskList = new SqliteList (this, "Project");
+                               AddTaskList (newTaskList);
                        }
                }
 
@@ -228,7 +229,7 @@ namespace Tasque.Backends.Sqlite
                        SqliteDataReader dataReader = cmd.ExecuteReader();
                        while(dataReader.Read()) {
                                int id = dataReader.GetInt32(0);
-                               int category = dataReader.GetInt32(1);
+                               int taskList = dataReader.GetInt32(1);
                                string name = dataReader.GetString(2);
                                long dueDate = dataReader.GetInt64(3);
                                long completionDate = dataReader.GetInt64(4);
@@ -237,9 +238,15 @@ namespace Tasque.Backends.Sqlite
                                
                                hasValues = true;
                                
-                               newTask = new SqliteTask(this, id, category,
-                                                        name, dueDate, completionDate,
-                                                        priority, state);
+                               newTask = new SqliteTask (this, id, name, dueDate,
+                                                         completionDate, priority, state);
+                               var list = TaskLists.Single (l => {
+                                       var sqliteList = l as SqliteList;
+                                       if (sqliteList != null)
+                                               return sqliteList.ID == taskList;
+                                       return false;
+                               });
+                               list.Add (newTask);
                                AddTask (newTask);
                                newTask.PropertyChanged += HandlePropertyChanged;
                        }
@@ -250,7 +257,7 @@ namespace Tasque.Backends.Sqlite
                        if(!hasValues)
                        {
                                newTask = new SqliteTask (this, "Create some tasks");
-                               newTask.Category = defaultCategory;
+                               defaultTaskList.Add (newTask);
                                newTask.DueDate = DateTime.Now;
                                newTask.Priority = TaskPriority.Medium;
                                AddTask (newTask);
@@ -265,14 +272,14 @@ namespace Tasque.Backends.Sqlite
                                task.PropertyChanged -= HandlePropertyChanged;
                }
 
-               void AddCategory (ICategory category)
+               void AddTaskList (TaskList taskList)
                {
-                       var index = categoryListStore.Count;
-                       var valIdx = categoryListStore.Select ((val, idx) => new { val, idx })
-                               .FirstOrDefault (x => categoryComparer.Compare (x.val, category) > 0);
+                       var index = taskListListStore.Count;
+                       var valIdx = taskListListStore.Select ((val, idx) => new { val, idx })
+                               .FirstOrDefault (x => taskListComparer.Compare (x.val, taskList) > 0);
                        if (valIdx != null)
                                index = valIdx.idx;
-                       categoryListStore.Insert (index, category);
+                       taskListListStore.Insert (index, taskList);
                }
                
                void AddTask (SqliteTask task)
diff --git a/src/Addins/Backends/Sqlite/SqliteBackend.csproj b/src/Addins/Backends/Sqlite/SqliteBackend.csproj
index c762a43..827a164 100644
--- a/src/Addins/Backends/Sqlite/SqliteBackend.csproj
+++ b/src/Addins/Backends/Sqlite/SqliteBackend.csproj
@@ -12,7 +12,7 @@
     <AssemblyName>SqliteBackend</AssemblyName>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
-    <ReleaseVersion>0.1.13</ReleaseVersion>
+    <ReleaseVersion>0.2.0</ReleaseVersion>
     <BuildEnabled>$(EnableBackendSqlite)</BuildEnabled>
     <PackageName>tasque</PackageName>
     <TopBuildDir>..\..\..\..</TopBuildDir>
@@ -88,7 +88,6 @@
   <ItemGroup>
     <Compile Include="SqliteTask.cs" />
     <Compile Include="SqliteNote.cs" />
-    <Compile Include="SqliteCategory.cs" />
     <Compile Include="SqliteBackend.cs" />
     <Compile Include="Database.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
@@ -96,6 +95,7 @@
       <Link>Properties\CommonAssemblyInfo.cs</Link>
     </Compile>
     <Compile Include="Gtk\SqlitePreferences.cs" />
+    <Compile Include="SqliteList.cs" />
   </ItemGroup>
   <ItemGroup>
     <Folder Include="Properties\" />
diff --git a/src/Addins/Backends/Sqlite/SqliteList.cs b/src/Addins/Backends/Sqlite/SqliteList.cs
new file mode 100644
index 0000000..0516bab
--- /dev/null
+++ b/src/Addins/Backends/Sqlite/SqliteList.cs
@@ -0,0 +1,80 @@
+// SqliteCategory.cs created with MonoDevelop
+// User: boyd at 9:06 AM 2/11/2008
+//
+// To change standard headers go to Edit->Preferences->Coding->Standard Headers
+//
+
+using System;
+using Tasque;
+
+namespace Tasque.Backends.Sqlite
+{
+       public class SqliteList : TaskList
+       {
+               private int id;
+               SqliteBackend backend;
+               
+               public int ID
+               {
+                       get { return id; }
+               }
+
+               public override bool IsReadOnly { get { return false; } }
+               
+               public string ExternalID
+               {
+                       get {
+                               string command = String.Format("SELECT ExternalID FROM Categories where 
ID='{0}'", id);
+                               return backend.Database.GetSingleString(command);
+                       }
+                       set {
+                               string command = String.Format("UPDATE Categories set ExternalID='{0}' where 
ID='{0}'", value, id);
+                               backend.Database.ExecuteScalar(command);
+                       }
+               }
+               
+               public SqliteList (SqliteBackend backend, string name)
+               {
+                       this.backend = backend;
+                       string command = String.Format("INSERT INTO Categories (Name, ExternalID) values 
('{0}', '{1}'); SELECT last_insert_rowid();", name, string.Empty);
+                       this.id = Convert.ToInt32 (backend.Database.ExecuteScalar(command));
+                       Name = name;
+                       //Logger.Debug("Inserted taskList named: {0} with id {1}", name, id);
+               }
+               
+               public SqliteList (SqliteBackend backend, int id, string name)
+               {
+                       this.backend = backend;
+                       this.id = id;
+                       Name = name;
+               }
+
+               protected override void OnNameChanging (ref string newName)
+               {
+                       newName = backend.SanitizeText (newName);
+                       base.OnNameChanging (ref newName);
+               }
+               
+               protected override void OnNameChanged ()
+               {
+                       var cmd = string.Format ("UPDATE Categories set Name='{0}' where ID='{0}'", Name, id);
+                       backend.Database.ExecuteNonQuery (cmd);
+                       base.OnNameChanged ();
+               }
+
+               protected override void OnAdded (Task newTask)
+               {
+                       var cmd = string.Format ("UPDATE Tasks set Category='{0}' where ID='{1}'", id, 
newTask.Id);
+                       backend.Database.ExecuteNonQuery (cmd);
+                       base.OnAdded (newTask);
+               }
+
+               protected override void OnRemoved (Task oldTask)
+               {
+                       // set cat to 1 for now, since this is always called in conjunction with Add
+                       var cmd = string.Format ("UPDATE Tasks set Category='{0}' where ID='{1}'", 1, 
oldTask.Id);
+                       backend.Database.ExecuteNonQuery (cmd);
+                       base.OnRemoved (oldTask);
+               }
+       }
+}
diff --git a/src/Addins/Backends/Sqlite/SqliteTask.cs b/src/Addins/Backends/Sqlite/SqliteTask.cs
index 513aa8f..dd8355f 100644
--- a/src/Addins/Backends/Sqlite/SqliteTask.cs
+++ b/src/Addins/Backends/Sqlite/SqliteTask.cs
@@ -11,157 +11,80 @@ namespace Tasque.Backends.Sqlite
        public class SqliteTask : Task
        {
                private SqliteBackend backend;
-               private int id;
-               private int category;
-               private string name;
-               private long dueDate;
-               private long completionDate;
-               private int priority;
-               private int state;
 
                public SqliteTask(SqliteBackend backend, string name)
                {
                        this.backend = backend;
-                       Logger.Debug("Creating New Task Object : {0} (id={1})", name, id);
+                       Logger.Debug("Creating New Task Object : {0} (id={1})", name, Id);
                        name = backend.SanitizeText (name);
-                       this.name = name;
-                       this.dueDate =  Database.FromDateTime(DateTime.MinValue);
-                       this.completionDate = Database.FromDateTime(DateTime.MinValue);
-                       this.category = 0;
-                       this.priority = (int)(TaskPriority.None);
-                       this.state = (int)TaskState.Active;
+                       Name = name;
                        string command = String.Format("INSERT INTO Tasks (Name, DueDate, CompletionDate, 
Priority, State, Category, ExternalID) values ('{0}','{1}', '{2}','{3}', '{4}', '{5}', '{6}'); SELECT 
last_insert_rowid();", 
-                                                               name, dueDate, completionDate,
-                                                               priority, state, category, string.Empty);
-                       this.id = Convert.ToInt32 (backend.Database.ExecuteScalar (command));
+                                                               name, Database.FromDateTime (DueDate), 
Database.FromDateTime (CompletionDate),
+                                                               0, (int)State, 0, string.Empty);
+                       Id = backend.Database.ExecuteScalar (command).ToString ();
                }
 
-               public SqliteTask (SqliteBackend backend, int id, int category, string name, 
+               public SqliteTask (SqliteBackend backend, int id, string name,
                                   long dueDate, long completionDate, int priority, int state)
                {
                        this.backend = backend;
-                       this.id = id;
-                       this.category = category;
-                       this.name = name;
-                       this.dueDate = dueDate;
-                       this.completionDate = completionDate;
-                       this.priority = priority;
-                       this.state = state;
-               }               
+                       Id = id.ToString ();
+                       Name = name;
+                       DueDate = Database.ToDateTime (dueDate);
+                       CompletionDate = Database.ToDateTime (completionDate);
+                       Priority = (TaskPriority)priority;
+                       State = (TaskState)state;
+               }
                
                #region Public Properties
-               
-               public override string Id
-               {
-                       get { return id.ToString(); }
-               }
 
-               internal int SqliteId
-               {
-                       get { return id; } 
-               }
-               
-               public override string Name
-               {
-                       get { return this.name; }
-                       set {
-                               OnPropertyChanging ("Name");
-                               string name = backend.SanitizeText (value);
-                               this.name = name;
-                               string command = String.Format("UPDATE Tasks set Name='{0}' where ID='{1}'", 
name, id);
-                               backend.Database.ExecuteScalar(command);
-                               OnPropertyChanged ("Name");
-                       }
-               }
-               
-               public override DateTime DueDate
+               protected override void OnNameChanging (ref string newName)
                {
-                       get { return Database.ToDateTime(this.dueDate); }
-                       set {
-                               OnPropertyChanging ("DueDate");
-                               this.dueDate = Database.FromDateTime(value);
-                               string command = String.Format("UPDATE Tasks set DueDate='{0}' where 
ID='{1}'", this.dueDate, id);
-                               backend.Database.ExecuteScalar(command);
-                               OnPropertyChanged ("DueDate");
-                       }
+                       newName = backend.SanitizeText (newName);
+                       base.OnNameChanging (ref newName);
                }
-               
-               
-               public override DateTime CompletionDate
+
+               protected override void OnNameChanged ()
                {
-                       get { return Database.ToDateTime(this.completionDate); }
-                       set {
-                               OnPropertyChanging ("CompletionDate");
-                               this.completionDate = Database.FromDateTime(value);
-                               string command = String.Format("UPDATE Tasks set CompletionDate='{0}' where 
ID='{1}'", this.completionDate, id);
-                               backend.Database.ExecuteScalar(command);
-                               OnPropertyChanged ("CompletionDate");
-                       }
+                       var cmd = string.Format ("UPDATE Tasks set Name='{0}' where ID='{1}'", Name, Id);
+                       backend.Database.ExecuteScalar (cmd);
+                       base.OnNameChanged ();
                }
-               
-               
-               public override bool IsComplete
+
+               protected override void OnDueDateChanged ()
                {
-                       get {
-                               if (CompletionDate == DateTime.MinValue)
-                                       return false;
-                               
-                               return true;
-                       }
+                       var lngDueDate = Database.FromDateTime (DueDate);
+                       var cmd = string.Format ("UPDATE Tasks set DueDate='{0}' where ID='{1}'", lngDueDate, 
Id);
+                       backend.Database.ExecuteScalar (cmd);
+                       base.OnDueDateChanged ();
                }
-               
-               public override TaskPriority Priority
+
+               protected override void OnCompletionDateChanged ()
                {
-                       get { return (TaskPriority) this.priority; }
-                       set {
-                               OnPropertyChanging ("Priority");
-                               this.priority = (int) value;
-                               string command = String.Format("UPDATE Tasks set Priority='{0}' where 
ID='{1}'", this.priority, id);
-                               backend.Database.ExecuteScalar(command);
-                               OnPropertyChanged ("Priority");
-                       }
+                       var lngCompletionDate = Database.FromDateTime (CompletionDate);
+                       var cmd = string.Format ("UPDATE Tasks set CompletionDate='{0}' where ID='{1}'", 
lngCompletionDate, Id);
+                       backend.Database.ExecuteScalar (cmd);
+                       base.OnCompleted ();
                }
 
-               public override bool HasNotes
+               protected override void OnPriorityChanged ()
                {
-                       get {
-                               string command = String.Format("SELECT COUNT(*) FROM Notes WHERE Task='{0}'", 
id);
-                               return backend.Database.GetSingleInt(command) > 0;
-                       }
+                       var intPriority = (int)Priority;
+                       var cmd = string.Format ("UPDATE Tasks set Priority='{0}' where ID='{1}'", 
intPriority, Id);
+                       backend.Database.ExecuteScalar (cmd);
+                       base.OnPriorityChanged ();
                }
                
-               public override NoteSupport NoteSupport
-               {
+               public override NoteSupport NoteSupport {
                        get { return NoteSupport.Multiple; }
                }
-               
-               public override TaskState State
-               {
-                       get { return LocalState; }
-               }
-               
-               public TaskState LocalState
-               {
-                       get { return (TaskState) this.state; }
-                       set {
-                               OnPropertyChanging ("State");
-                               this.state = (int) value;
-                               string command = String.Format("UPDATE Tasks set State='{0}' where ID='{1}'", 
this.state, id);
-                               backend.Database.ExecuteScalar(command);
-                               OnPropertyChanged ("State");
-                       }
-               }
 
-               public override ICategory Category
+               protected override void OnStateChanged ()
                {
-                       get { return new SqliteCategory(backend, this.category); }
-                       set {
-                               OnPropertyChanging ("Category");
-                               this.category = (int)(value as SqliteCategory).ID;
-                               string command = String.Format("UPDATE Tasks set Category='{0}' where 
ID='{1}'", category, id);
-                               backend.Database.ExecuteScalar(command);
-                               OnPropertyChanged ("Category");
-                       }
+                       var intState = (int)State;
+                       var command = string.Format ("UPDATE Tasks set State='{0}' where ID='{1}'", intState, 
Id);
+                       backend.Database.ExecuteScalar (command);
+                       base.OnStateChanged ();
                }
                
                public override List<INote> Notes
@@ -169,7 +92,7 @@ namespace Tasque.Backends.Sqlite
                        get {
                                List<INote> notes = new List<INote>();
 
-                               string command = String.Format("SELECT ID, Text FROM Notes WHERE Task='{0}'", 
id);
+                               string command = String.Format("SELECT ID, Text FROM Notes WHERE Task='{0}'", 
Id);
                                SqliteCommand cmd = backend.Database.Connection.CreateCommand();
                                cmd.CommandText = command;
                                SqliteDataReader dataReader = cmd.ExecuteReader();
@@ -186,32 +109,18 @@ namespace Tasque.Backends.Sqlite
                #endregion // Public Properties
                
                #region Public Methods
-               public override void Activate ()
-               {
-                       // Logger.Debug ("SqliteTask.Activate ()");
-                       LocalState = TaskState.Active;
-                       CompletionDate = DateTime.MinValue;
-               }
-               
-               public override void Complete ()
-               {
-                       //Logger.Debug ("SqliteTask.Complete ()");
-                       LocalState = TaskState.Completed;
-                       CompletionDate = DateTime.Now;
-               }
-               
-               public override void Delete ()
+
+               protected override void OnDeleted ()
                {
-                       //Logger.Debug ("SqliteTask.Delete ()");
-                       LocalState = TaskState.Deleted;
                        backend.DeleteTask (this);
+                       base.OnDeleted ();
                }
                
                public override INote CreateNote(string text)
                {
-                       Logger.Debug("Creating New Note Object : {0} (id={1})", text, id);
+                       Logger.Debug("Creating New Note Object : {0} (id={1})", text, Id);
                        text = backend.SanitizeText (text);
-                       string command = String.Format("INSERT INTO Notes (Task, Text) VALUES ('{0}','{1}'); 
SELECT last_insert_rowid();", id, text);
+                       string command = String.Format("INSERT INTO Notes (Task, Text) VALUES ('{0}','{1}'); 
SELECT last_insert_rowid();", Id, text);
                        int taskId = Convert.ToInt32 (backend.Database.ExecuteScalar(command));
 
                        return new SqliteNote (taskId, text);
diff --git a/src/Addins/Gtk.Tasque.Columns/CompleteColumn.cs b/src/Addins/Gtk.Tasque.Columns/CompleteColumn.cs
index e30a6d1..d6d4057 100644
--- a/src/Addins/Gtk.Tasque.Columns/CompleteColumn.cs
+++ b/src/Addins/Gtk.Tasque.Columns/CompleteColumn.cs
@@ -26,6 +26,7 @@
 using System;
 using Mono.Unix;
 using Tasque;
+using Tasque.Core;
 
 namespace Gtk.Tasque
 {
diff --git a/src/Addins/Gtk.Tasque.Columns/DueDateColumn.cs b/src/Addins/Gtk.Tasque.Columns/DueDateColumn.cs
index d59f06a..62709d8 100644
--- a/src/Addins/Gtk.Tasque.Columns/DueDateColumn.cs
+++ b/src/Addins/Gtk.Tasque.Columns/DueDateColumn.cs
@@ -26,6 +26,7 @@
 using System;
 using Mono.Unix;
 using Tasque;
+using Tasque.Core;
 
 namespace Gtk.Tasque
 {
@@ -112,7 +113,7 @@ namespace Gtk.Tasque
                                        
                                        var newDate = DateTime.MinValue;
                                        var tday = DateTime.Now;
-                                       var task = model.GetValue (iter, 0) as ITask;                   
+                                       var task = model.GetValue (iter, 0) as ITask;
                                        
                                        if (newText == tday.ToString (Catalog.GetString ("M/d - ")) + 
Catalog.GetString ("Today"))
                                                newDate = tday;
@@ -140,10 +141,7 @@ namespace Gtk.Tasque
                                        
                                        Logger.Debug ("task.State {0}", task.State);
                                        
-                                       if (task.State == TaskState.Completed) {
-                                               // Modify the completion date
-                                               task.CompletionDate = newDate;
-                                       } else {
+                                       if (task.State != TaskState.Completed) {
                                                // Modify the due date
                                                task.DueDate = newDate;
                                        }
diff --git a/src/Addins/Gtk.Tasque.Columns/Gtk.Tasque.Columns.csproj 
b/src/Addins/Gtk.Tasque.Columns/Gtk.Tasque.Columns.csproj
index 3048a86..7ff39a6 100644
--- a/src/Addins/Gtk.Tasque.Columns/Gtk.Tasque.Columns.csproj
+++ b/src/Addins/Gtk.Tasque.Columns/Gtk.Tasque.Columns.csproj
@@ -12,7 +12,7 @@
     <AssemblyName>Gtk.Tasque.Columns</AssemblyName>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
-    <ReleaseVersion>0.1.13</ReleaseVersion>
+    <ReleaseVersion>0.2.0</ReleaseVersion>
     <PackageName>tasque</PackageName>
     <TopBuildDir>..\..\..</TopBuildDir>
   </PropertyGroup>
@@ -61,6 +61,10 @@
       <Private>False</Private>
       <Package>gtk-sharp-2.0</Package>
     </Reference>
+    <Reference Include="glib-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f">
+      <Private>False</Private>
+      <Package>glib-sharp-2.0</Package>
+    </Reference>
   </ItemGroup>
   <ItemGroup>
     <Compile Include="Properties\AssemblyInfo.cs" />
diff --git a/src/Addins/Gtk.Tasque.Columns/NotesColumn.cs b/src/Addins/Gtk.Tasque.Columns/NotesColumn.cs
index e5382ac..e6fa545 100644
--- a/src/Addins/Gtk.Tasque.Columns/NotesColumn.cs
+++ b/src/Addins/Gtk.Tasque.Columns/NotesColumn.cs
@@ -26,8 +26,10 @@
 using System;
 using Mono.Unix;
 using Tasque;
+using Tasque.Core;
 using Gdk;
 
+
 namespace Gtk.Tasque
 {
        public class NotesColumn : ITaskColumn
diff --git a/src/Addins/Gtk.Tasque.Columns/PriorityColumn.cs b/src/Addins/Gtk.Tasque.Columns/PriorityColumn.cs
index 8d0a685..2e1a97b 100644
--- a/src/Addins/Gtk.Tasque.Columns/PriorityColumn.cs
+++ b/src/Addins/Gtk.Tasque.Columns/PriorityColumn.cs
@@ -26,6 +26,7 @@
 using System;
 using Mono.Unix;
 using Tasque;
+using Tasque.Core;
 
 namespace Gtk.Tasque
 {
diff --git a/src/Addins/Gtk.Tasque.Columns/Properties/AssemblyInfo.cs 
b/src/Addins/Gtk.Tasque.Columns/Properties/AssemblyInfo.cs
index 5437498..1cd1ec8 100644
--- a/src/Addins/Gtk.Tasque.Columns/Properties/AssemblyInfo.cs
+++ b/src/Addins/Gtk.Tasque.Columns/Properties/AssemblyInfo.cs
@@ -29,4 +29,4 @@ using Mono.Addins;
 [assembly: AssemblyTitle("Gtk.Tasque.Columns")]
 [assembly: AssemblyDescription("Standard Task Columns for the Gtk# frontend of Tasque")]
 [assembly: Addin]
-[assembly: AddinDependency ("GtkTasque", "0.1.13")]
+[assembly: AddinDependency ("GtkTasque", "0.2.0")]
diff --git a/src/Addins/Gtk.Tasque.Columns/TaskBeingEdited.cs 
b/src/Addins/Gtk.Tasque.Columns/TaskBeingEdited.cs
index b512014..5c299f9 100644
--- a/src/Addins/Gtk.Tasque.Columns/TaskBeingEdited.cs
+++ b/src/Addins/Gtk.Tasque.Columns/TaskBeingEdited.cs
@@ -24,7 +24,7 @@
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 // THE SOFTWARE.
 using System;
-using Tasque;
+using Tasque.Core;
 
 namespace Gtk.Tasque
 {
diff --git a/src/Addins/Gtk.Tasque.Columns/TaskNameColumn.cs b/src/Addins/Gtk.Tasque.Columns/TaskNameColumn.cs
index 3d62ec8..5bbb36b 100644
--- a/src/Addins/Gtk.Tasque.Columns/TaskNameColumn.cs
+++ b/src/Addins/Gtk.Tasque.Columns/TaskNameColumn.cs
@@ -27,6 +27,8 @@ using System;
 using Mono.Unix;
 using Tasque;
 using GLib;
+using Tasque.Core;
+using Tasque.DateFormatters;
 
 namespace Gtk.Tasque
 {
@@ -91,7 +93,7 @@ namespace Gtk.Tasque
                                                newText = parsedTaskText;
                                        }
                                        
-                                       task.Name = newText;
+                                       task.Text = newText;
                                }
                                EndCellEditing ();
                        };
@@ -160,7 +162,7 @@ namespace Gtk.Tasque
 //                             if (timer != null && timer.State == TaskCompleteTimerState.Running)
 //                                     formatString = "<span strikethrough=\"true\">{0}</span>";
 //                             break;
-                       case TaskState.Deleted:
+                       case TaskState.Discarded:
                        case TaskState.Completed:
                                // Gray out the text and add strikeout
                                // TODO: Determine the grayed-out text color appropriate for the current theme
@@ -169,7 +171,7 @@ namespace Gtk.Tasque
                                break;
                        }
                        
-                       crt.Markup = string.Format (formatString, Markup.EscapeText (task.Name));
+                       crt.Markup = string.Format (formatString, Markup.EscapeText (task.Text));
                }
 
                TreeModel model;
diff --git a/src/Addins/Gtk.Tasque.TimerCompleteColumns/CompleteWithTimerColumn.cs 
b/src/Addins/Gtk.Tasque.TimerCompleteColumns/CompleteWithTimerColumn.cs
index 5a89fc5..9b19652 100644
--- a/src/Addins/Gtk.Tasque.TimerCompleteColumns/CompleteWithTimerColumn.cs
+++ b/src/Addins/Gtk.Tasque.TimerCompleteColumns/CompleteWithTimerColumn.cs
@@ -26,6 +26,7 @@
 using System;
 using Mono.Unix;
 using Tasque;
+using Tasque.Core;
 
 namespace Gtk.Tasque
 {
diff --git a/src/Addins/Gtk.Tasque.TimerCompleteColumns/Gtk.Tasque.TimerCompleteColumns.csproj 
b/src/Addins/Gtk.Tasque.TimerCompleteColumns/Gtk.Tasque.TimerCompleteColumns.csproj
index d0973b6..5acb265 100644
--- a/src/Addins/Gtk.Tasque.TimerCompleteColumns/Gtk.Tasque.TimerCompleteColumns.csproj
+++ b/src/Addins/Gtk.Tasque.TimerCompleteColumns/Gtk.Tasque.TimerCompleteColumns.csproj
@@ -12,7 +12,7 @@
     <AssemblyName>Gtk.Tasque.TimerCompleteColumns</AssemblyName>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
-    <ReleaseVersion>0.1.13</ReleaseVersion>
+    <ReleaseVersion>0.2.0</ReleaseVersion>
     <PackageName>tasque</PackageName>
     <TopBuildDir>..\..\..</TopBuildDir>
   </PropertyGroup>
diff --git a/src/Addins/Gtk.Tasque.TimerCompleteColumns/Properties/AssemblyInfo.cs 
b/src/Addins/Gtk.Tasque.TimerCompleteColumns/Properties/AssemblyInfo.cs
index 3182b10..af53b1d 100644
--- a/src/Addins/Gtk.Tasque.TimerCompleteColumns/Properties/AssemblyInfo.cs
+++ b/src/Addins/Gtk.Tasque.TimerCompleteColumns/Properties/AssemblyInfo.cs
@@ -29,4 +29,4 @@ using Mono.Addins;
 [assembly: AssemblyTitle("Gtk.Tasque.TimerCompleteColumns")]
 [assembly: AssemblyDescription("Timed completion columns for the Gtk# frontend of Tasque")]
 [assembly: Addin]
-[assembly: AddinDependency ("GtkTasque", "0.1.13")]
+[assembly: AddinDependency ("GtkTasque", "0.2.0")]
diff --git a/src/Addins/Gtk.Tasque.TimerCompleteColumns/TaskCompleteTimer.cs 
b/src/Addins/Gtk.Tasque.TimerCompleteColumns/TaskCompleteTimer.cs
index e2d9e31..74bf284 100644
--- a/src/Addins/Gtk.Tasque.TimerCompleteColumns/TaskCompleteTimer.cs
+++ b/src/Addins/Gtk.Tasque.TimerCompleteColumns/TaskCompleteTimer.cs
@@ -24,7 +24,7 @@
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 // THE SOFTWARE.
 using System;
-using Tasque;
+using Tasque.Core;
 using Gdk;
 
 namespace Gtk.Tasque
diff --git a/src/Addins/Gtk.Tasque.TimerCompleteColumns/TaskCompleteTimerStoppedEventArgs.cs 
b/src/Addins/Gtk.Tasque.TimerCompleteColumns/TaskCompleteTimerStoppedEventArgs.cs
index 7d52791..d3343e7 100644
--- a/src/Addins/Gtk.Tasque.TimerCompleteColumns/TaskCompleteTimerStoppedEventArgs.cs
+++ b/src/Addins/Gtk.Tasque.TimerCompleteColumns/TaskCompleteTimerStoppedEventArgs.cs
@@ -24,7 +24,7 @@
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 // THE SOFTWARE.
 using System;
-using Tasque;
+using Tasque.Core;
 
 namespace Gtk.Tasque
 {
diff --git a/src/Addins/Gtk.Tasque.TimerCompleteColumns/TaskCompleteTimerTickEventArgs.cs 
b/src/Addins/Gtk.Tasque.TimerCompleteColumns/TaskCompleteTimerTickEventArgs.cs
index 13be62c..3e5f589 100644
--- a/src/Addins/Gtk.Tasque.TimerCompleteColumns/TaskCompleteTimerTickEventArgs.cs
+++ b/src/Addins/Gtk.Tasque.TimerCompleteColumns/TaskCompleteTimerTickEventArgs.cs
@@ -24,7 +24,7 @@
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 // THE SOFTWARE.
 using System;
-using Tasque;
+using Tasque.Core;
 
 namespace Gtk.Tasque
 {
diff --git a/src/Addins/Gtk.Tasque.TimerCompleteColumns/TimerColumn.cs 
b/src/Addins/Gtk.Tasque.TimerCompleteColumns/TimerColumn.cs
index 9cca6a4..b366625 100644
--- a/src/Addins/Gtk.Tasque.TimerCompleteColumns/TimerColumn.cs
+++ b/src/Addins/Gtk.Tasque.TimerCompleteColumns/TimerColumn.cs
@@ -27,13 +27,14 @@ using System;
 using System.Collections.Concurrent;
 using Mono.Unix;
 using Tasque;
+using Tasque.Core;
 
 namespace Gtk.Tasque
 {
        // TODO: Use xml addin description model to provide localized column name
        [TaskColumnExtension ("Timer")]
        public class TimerColumn : ITaskColumn
-       {               
+       {
                public TimerColumn ()
                {
                        timeoutTargets = new ConcurrentDictionary<ITask, TaskCompleteTimer> ();
@@ -64,13 +65,13 @@ namespace Gtk.Tasque
                        this.preferences = preferences;
                        
                        view.RowEditingStarted += (sender, e) => {
-                               var timer = GetTimer (e.Task);
+                               var timer = GetTimer (e.ITask);
                                if (timer != null && timer.State == TaskCompleteTimerState.Running)
                                        timer.Pause ();
                        };
                        
                        view.RowEditingFinished += (sender, e) => {
-                               var timer = GetTimer (e.Task);
+                               var timer = GetTimer (e.ITask);
                                if (timer != null && timer.State == TaskCompleteTimerState.Paused)
                                        timer.Resume ();
                        };
diff --git a/src/Gtk.Tasque/AppIndicatorTray.cs b/src/Gtk.Tasque/AppIndicatorTray.cs
index e561d2d..4810538 100644
--- a/src/Gtk.Tasque/AppIndicatorTray.cs
+++ b/src/Gtk.Tasque/AppIndicatorTray.cs
@@ -23,7 +23,6 @@
 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 // THE SOFTWARE.
-using Tasque;
 using Gtk;
 using AppIndicator;
 
@@ -31,7 +30,7 @@ namespace Gtk.Tasque
 {
        public class AppIndicatorTray : GtkTray
        {
-               public AppIndicatorTray (INativeApplication application) : base  (application)
+               public AppIndicatorTray (GtkApplicationBase application) : base  (application)
                {
                        appIndicator = new ApplicationIndicator ("TasqueTray", IconName, 
Category.ApplicationStatus);
                        appIndicator.Status = Status.Active;
diff --git a/src/Gtk.Tasque/CellRendererDate.cs b/src/Gtk.Tasque/CellRendererDate.cs
index 88a5111..22ed3ea 100644
--- a/src/Gtk.Tasque/CellRendererDate.cs
+++ b/src/Gtk.Tasque/CellRendererDate.cs
@@ -2,7 +2,7 @@
 using System;
 using Mono.Unix;
 using Gtk;
-using Tasque;
+using Gtk.Tasque;
 
 namespace Gtk.Extras
 {
diff --git a/src/Gtk.Tasque/CompletedTaskGroup.cs b/src/Gtk.Tasque/CompletedTaskGroup.cs
index f44e31b..69bcd75 100644
--- a/src/Gtk.Tasque/CompletedTaskGroup.cs
+++ b/src/Gtk.Tasque/CompletedTaskGroup.cs
@@ -12,6 +12,8 @@ using System.Linq;
 using Mono.Unix;
 using Gtk;
 using Gtk.Tasque;
+using Tasque.Core;
+using Tasque.Utils;
 
 namespace Tasque
 {
@@ -26,12 +28,12 @@ namespace Tasque
        
        public class CompletedTaskGroup : TaskGroup
        {
-               ICategory selectedCategory;
+               ITaskList selectedTaskList;
                HScale rangeSlider;
                ShowCompletedRange currentRange;
                
                public CompletedTaskGroup (string groupName, DateTime rangeStart,
-                                          DateTime rangeEnd, ICollection<ITask> tasks, INativeApplication 
application)
+                                          DateTime rangeEnd, ICollection<ITask> tasks, GtkApplicationBase 
application)
                        : base (groupName, rangeStart, rangeEnd, new CompletedTasksSortModel(tasks), 
application)
                {
                        var preferences = application.Preferences;
@@ -47,13 +49,13 @@ namespace Tasque
                                        HideWhenEmpty = !prefs.GetBool 
(PreferencesKeys.ShowCompletedTasksKey);
                                        
                                        // refresh ui
-                                       var cat = GetSelectedCategory ();
+                                       var cat = GetSelectedTaskList ();
                                        if (cat != null)
                                                Refilter (cat);
                                        break;
-                               case PreferencesKeys.SelectedCategoryKey:
-                                       selectedCategory = GetSelectedCategory ();
-                                       Refilter (selectedCategory);
+                               case PreferencesKeys.SelectedTaskListKey:
+                                       selectedTaskList = GetSelectedTaskList ();
+                                       Refilter (selectedTaskList);
                                        break;
                                }
                        };
@@ -103,18 +105,18 @@ namespace Tasque
                        return new TreeModelListAdapter<ITask> (Model);
                }
                
-               protected ICategory GetSelectedCategory ()
+               protected ITaskList GetSelectedTaskList ()
                {
-                       ICategory foundCategory = null;
+                       ITaskList foundTaskList = null;
                        
                        string cat = Application.Preferences.Get (
-                               PreferencesKeys.SelectedCategoryKey);
+                               PreferencesKeys.SelectedTaskListKey);
                        if (cat != null) {
-                               var model = Application.Backend.Categories;
-                               foundCategory = model.FirstOrDefault (c => c.Name == cat);
+                               var model = Application.BackendManager.TaskLists;
+                               foundTaskList = model.FirstOrDefault (c => c.Name == cat);
                        }
                        
-                       return foundCategory;
+                       return foundTaskList;
                }
                
                private void OnRangeSliderChanged (object sender, EventArgs args)
@@ -215,6 +217,7 @@ namespace Tasque
        {
                public CompletedTasksSortModel (ICollection<ITask> childModel)
                {
+                       completionDateComparer = new TaskCompletionDateComparer ();
                        originalTasks = childModel;
                        ((INotifyCollectionChanged)childModel).CollectionChanged += HandleCollectionChanged;
                        foreach (var item in originalTasks)
@@ -253,10 +256,11 @@ namespace Tasque
                                return 0;
                        
                        // Reverse the logic with the '-' so it's in reverse
-                       return -(x.CompareToByCompletionDate (y));
+                       return -(completionDateComparer.Compare (x, y));
                }
                #endregion // Private Methods
                
                ICollection<ITask> originalTasks;
+               TaskCompletionDateComparer completionDateComparer;
        }
 }
diff --git a/src/Gtk.Tasque/DateButton.cs b/src/Gtk.Tasque/DateButton.cs
index e2d01c4..6bcb06a 100644
--- a/src/Gtk.Tasque/DateButton.cs
+++ b/src/Gtk.Tasque/DateButton.cs
@@ -29,7 +29,7 @@
 using System;
 using GLib;
 using Gtk;
-using Tasque;
+using Gtk.Tasque;
 
 namespace Gtk.Extras
 {
diff --git a/src/Gtk.Tasque/Defines.cs.in b/src/Gtk.Tasque/Defines.cs.in
index 43d72d4..5b5b051 100644
--- a/src/Gtk.Tasque/Defines.cs.in
+++ b/src/Gtk.Tasque/Defines.cs.in
@@ -34,7 +34,7 @@ using System.Configuration;
 using System.IO;
 using Mono.Unix;
 
-namespace Tasque
+namespace Gtk.Tasque
 {
        public static class Defines
        {
diff --git a/src/Gtk.Tasque/Gtk.Tasque.csproj b/src/Gtk.Tasque/Gtk.Tasque.csproj
index ac89ef7..f271d76 100644
--- a/src/Gtk.Tasque/Gtk.Tasque.csproj
+++ b/src/Gtk.Tasque/Gtk.Tasque.csproj
@@ -6,14 +6,14 @@
     <ProjectGuid>{B19B9840-669D-4984-9772-E1F55193A67F}</ProjectGuid>
     <ProductVersion>10.0.0</ProductVersion>
     <SchemaVersion>2.0</SchemaVersion>
-    <OutputType>Library</OutputType>
+    <OutputType>WinExe</OutputType>
     <OutputPath>.</OutputPath>
-    <AssemblyName>Gtk.Tasque</AssemblyName>
+    <AssemblyName>Tasque</AssemblyName>
     <RootNamespace>Gtk.Tasque</RootNamespace>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
     <GtkSharp12 Condition=" '$(EnableGtkSharp12)' == '' Or '$(EnableGtkSharp12)' ">GTK_2_12</GtkSharp12>
-    <ReleaseVersion>0.1.13</ReleaseVersion>
+    <ReleaseVersion>0.2.0</ReleaseVersion>
     <PackageName>tasque</PackageName>
     <TopBuildDir>..\..</TopBuildDir>
   </PropertyGroup>
@@ -50,33 +50,47 @@
   </PropertyGroup>
   <ItemGroup>
     <Reference Include="System" />
-    <Reference Include="System.configuration" />
     <Reference Include="System.Data" />
     <Reference Include="System.Xml" />
-    <Reference Include="atk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
-    <Reference Include="gdk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
-    <Reference Include="glib-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
-    <Reference Include="gtk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
-    <Reference Include="pango-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
+    <Reference Include="atk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f">
+      <Package>gtk-sharp-2.0</Package>
+    </Reference>
+    <Reference Include="gdk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f">
+      <Package>gtk-sharp-2.0</Package>
+    </Reference>
+    <Reference Include="glib-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f">
+      <Package>glib-sharp-2.0</Package>
+    </Reference>
+    <Reference Include="gtk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f">
+      <Package>gtk-sharp-2.0</Package>
+    </Reference>
+    <Reference Include="pango-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f">
+      <Package>gtk-sharp-2.0</Package>
+    </Reference>
     <Reference Include="Mono.Posix" />
     <Reference Include="Mono.Data.Sqlite" />
     <Reference Include="appindicator-sharp, Version=0.2.0.0, Culture=neutral, 
PublicKeyToken=bcae265d1c7ab4c2">
       <Private>False</Private>
+      <Package>appindicator-sharp-0.1</Package>
     </Reference>
     <Reference Include="notify-sharp, Version=0.4.0.0, Culture=neutral, PublicKeyToken=2df29c54e245917a">
       <Private>False</Private>
+      <Package>notify-sharp</Package>
     </Reference>
     <Reference Include="dbus-sharp, Version=1.0.0.0, Culture=neutral, PublicKeyToken=5675b0c3093115b5">
       <Private>False</Private>
+      <Package>dbus-sharp-1.0</Package>
     </Reference>
     <Reference Include="dbus-sharp-glib, Version=1.0.0.0, Culture=neutral, PublicKeyToken=5675b0c3093115b5">
       <Private>False</Private>
+      <Package>dbus-sharp-glib-1.0</Package>
     </Reference>
     <Reference Include="System.Core" />
     <Reference Include="Mono.Addins, Version=0.6.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756">
       <Private>False</Private>
       <Package>mono-addins</Package>
     </Reference>
+    <Reference Include="System.Configuration" />
   </ItemGroup>
   <ItemGroup>
     <ProjectReference Include="..\libtasque\libtasque.csproj">
@@ -94,7 +108,6 @@
     <Compile Include="DateButton.cs" />
     <Compile Include="NoteDialog.cs" />
     <Compile Include="NoteWidget.cs" />
-    <None Include="OSXApplication.cs" />
     <Compile Include="PreferencesDialog.cs" />
     <Compile Include="TaskCalendar.cs" />
     <Compile Include="TaskGroup.cs" />
@@ -112,12 +125,29 @@
     <Compile Include="TaskColumnExtensionAttribute.cs" />
     <Compile Include="TaskRowEditingEventArgs.cs" />
     <Compile Include="TaskView.cs" />
+    <Compile Include="Program.cs" />
+    <Compile Include="..\Options.cs">
+      <Link>Options.cs</Link>
+    </Compile>
   </ItemGroup>
   <ItemGroup Condition=" '$(Configuration)' == 'LinuxDebug' Or '$(Configuration)' == 'LinuxRelease' ">
     <Compile Include="RemoteControl.cs" />
   </ItemGroup>
   <ItemGroup>
     <Substitute Include="Defines.cs.in" />
+    <Substitute Include="Tasque.exe.Defines.config.in" />
+    <Substitute Include="tasque.in" />
+    <Substitute Include="tasque.pc.in" />
+  </ItemGroup>
+  <ItemGroup>
+    <DistFile Include="Tasque.exe.config">
+      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+    </DistFile>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Tasque.exe.Defines.config">
+      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+    </None>
   </ItemGroup>
   <ItemGroup>
     <Folder Include="Properties\" />
@@ -134,4 +164,21 @@
       <Output TaskParameter="Include" ItemName="Substitution" />
     </CreateItem>
   </Target>
+  <Target Name="AfterSubstitute" Condition=" '$(Configuration)' == 'GtkLinuxDebug' Or '$(Configuration)' == 
'GtkLinuxRelease' ">
+    <Exec Command="chmod +x tasque" />
+  </Target>
+  <Target Name="SetupInstallFile">
+    <CreateItem Condition="'$(Configuration)' == 'GtkLinuxDebug' Or '$(Configuration)' == 'GtkLinuxRelease' 
" Include="$(SrcDir)\Tasque.exe.config" 
AdditionalMetadata="InstallPath=$(PkgLibDir);InstallFileName=Tasque.exe.config;Executable=false">
+      <Output TaskParameter="Include" ItemName="InstallFile" />
+    </CreateItem>
+    <CreateItem Include="Tasque.exe.Defines.config" 
AdditionalMetadata="InstallPath=$(PkgLibDir);InstallFileName=Tasque.exe.Defines.config;Executable=false">
+      <Output TaskParameter="Include" ItemName="InstallFile" />
+    </CreateItem>
+    <CreateItem Include="tasque.pc" 
AdditionalMetadata="InstallPath=$(PkgConfigDir);InstallFileName=tasque.pc;Executable=false">
+      <Output TaskParameter="Include" ItemName="InstallFile" />
+    </CreateItem>
+    <CreateItem Include="tasque" 
AdditionalMetadata="InstallPath=$(BinDir);InstallFileName=tasque;Executable=true">
+      <Output TaskParameter="Include" ItemName="InstallFile" />
+    </CreateItem>
+  </Target>
 </Project>
diff --git a/src/Gtk.Tasque/GtkApplicationBase.cs b/src/Gtk.Tasque/GtkApplicationBase.cs
index 63210f1..211b37c 100644
--- a/src/Gtk.Tasque/GtkApplicationBase.cs
+++ b/src/Gtk.Tasque/GtkApplicationBase.cs
@@ -1,36 +1,41 @@
-// 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. 
+// 
+// GtkApplicationBase.cs
+// 
+// Authors:
+//       Sandy Armstrong <sanfordarmstrong gmail com>
+//       Antonius Riha <antoniusriha gmail com>
 // 
 // Copyright (c) 2008 Novell, Inc. (http://www.novell.com) 
-// Copyright (c) 2012 Antonius Riha
+// Copyright (c) 2012-2013 Antonius Riha
 // 
-// Authors: 
-//      Sandy Armstrong <sanfordarmstrong gmail com>
-//      Antonius Riha <antoniusriha gmail com>
+// 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.Diagnostics;
 using System.IO;
+using System.Linq;
 using Mono.Addins;
+using Mono.Options;
 using Mono.Unix;
 using Tasque;
+using Tasque.Core;
+using Tasque.Utils;
 using Gtk;
+using System.Collections.Generic;
 
 #if ENABLE_NOTIFY_SHARP
 using Notifications;
@@ -38,68 +43,155 @@ using Notifications;
 
 namespace Gtk.Tasque
 {
-       public abstract class GtkApplicationBase : NativeApplication
+       public abstract class GtkApplicationBase : IDisposable
        {
-               protected GtkApplicationBase ()
+               protected GtkApplicationBase (string[] args)
                {
                        AddinManager.Initialize ();
                        AddinManager.Registry.Update ();
+
+                       Catalog.Init ("tasque", Defines.LocaleDir);
                        
-                       confDir = Path.Combine (Environment.GetFolderPath (
+                       ConfDir = Path.Combine (Environment.GetFolderPath (
                                Environment.SpecialFolder.ApplicationData), "tasque");
-                       if (!Directory.Exists (confDir))
-                               Directory.CreateDirectory (confDir);
-               }
-               
-               public override string ConfDir { get { return confDir; } }
+                       if (!Directory.Exists (ConfDir))
+                               Directory.CreateDirectory (ConfDir);
 
-               protected override void OnInitialize ()
-               {
-                       Catalog.Init ("tasque", Defines.LocaleDir);
+                       if (IsRemoteInstanceRunning ()) {
+                               Logger.Info ("Another instance of Tasque is already running.");
+                               Exit (0);
+                       }
+                       
+                       RemoteInstanceKnocked += delegate {
+                               TaskWindow.ShowWindow (this);
+                       };
+                       
+                       preferences = new Preferences (ConfDir);
+                       
+                       ParseArgs (args);
+                       
+                       backendManager = new BackendManager (preferences);
+                       backendManager.BackendConfigurationRequested += delegate {
+                               ShowPreferences ();
+                       };
+                       
                        Gtk.Application.Init ();
                        
                        // add package icon path to default icon theme search paths
                        IconTheme.Default.PrependSearchPath (Defines.IconsDir);
-
+                       
                        Gtk.Application.Init ();
                        GLib.Idle.Add (delegate {
                                InitializeIdle ();
                                return false;
                        });
-
+                       
                        GLib.Timeout.Add (60000, delegate {
                                CheckForDaySwitch ();
                                return true;
                        });
-
-                       Gtk.Application.Run ();
                        
-                       base.OnInitialize ();
+                       Gtk.Application.Run ();
                }
                
-               protected override void OnInitializeIdle ()
+               public BackendManager BackendManager { get { return backendManager; } }
+               
+               public string ConfDir { get; private set; }
+               
+               public IPreferences Preferences { get { return preferences; } }
+
+               protected void InitializeIdle ()
                {
+                       string backend = null;
+                       if (customBackendId != null)
+                               backend = customBackendId;
+                       else {
+                               var backendIdString = preferences.Get (PreferencesKeys.CurrentBackend);
+                               Logger.Debug ("CurrentBackend specified in Preferences: {0}",
+                                             backendIdString);
+                               var bs = backendManager.AvailableBackends.SingleOrDefault (
+                                       b => b.Key == backendIdString).Key;
+                               if (!string.IsNullOrWhiteSpace (bs))
+                                       backend = bs;
+                       }
+                       
+                       backendManager.SetBackend (backend);
+                       
                        trayIcon = GtkTray.CreateTray (this);
                        
-                       if (Backend == null) {
+                       BackendManager.BackendChanging += delegate {
+                               backendWasNullBeforeChange = BackendManager.CurrentBackend == null;
+                       };
+                       
+                       BackendManager.BackendInitialized += delegate {
+                               if (backendWasNullBeforeChange)
+                                       TaskWindow.Reinitialize (!quietStart, this);
+                               else
+                                       TaskWindow.Reinitialize (true, this);
+                               
+                               if (trayIcon != null)
+                                       trayIcon.RefreshTrayIconTooltip ();
+                       };
+                       
+                       if (backendManager.CurrentBackend == null) {
                                // Pop open the preferences dialog so the user can choose a
                                // backend service to use.
                                ShowPreferences ();
-                       } else if (!QuietStart)
+                       } else if (!quietStart)
                                TaskWindow.ShowWindow (this);
                        
-                       if (Backend == null || !Backend.Configured) {
+                       if (backendManager.CurrentBackend == null ||
+                           !backendManager.IsBackendConfigured) {
                                GLib.Timeout.Add (1000, new GLib.TimeoutHandler (delegate {
-                                       RetryBackend ();
-                                       return Backend == null || !Backend.Configured;
+                                       try {
+                                               if (backendManager.CurrentBackend != null &&
+                                                   !backendManager.IsBackendConfigured) {
+                                                       backendManager.ReInitializeBackend ();
+                                               }
+                                       } catch (Exception e) {
+                                               Logger.Error ("{0}", e.Message);
+                                       }
+                                       return backendManager.CurrentBackend == null ||
+                                               !backendManager.IsBackendConfigured;
                                }));
                        }
                        
-                       base.OnInitializeIdle ();
+                       OnInitializeIdle ();
+               }
+
+               public void Exit (int exitcode = 0)
+               {
+                       Logger.Info ("Exit called - terminating application");
+                       
+                       if (backendManager != null)
+                               backendManager.Dispose ();
+                       
+                       TaskWindow.SavePosition (Preferences);
+                       Application.Quit ();
+                       
+                       if (Exiting != null)
+                               Exiting (this, EventArgs.Empty);
+                       
+                       Environment.Exit (exitcode);
+               }
+
+               /// <summary>
+               /// Releases all resource used by the <see cref="Gtk.Tasque.GtkApplicationBase"/> object.
+               /// </summary>
+               /// <remarks>
+               /// Call <see cref="Dispose"/> when you are finished using the <see 
cref="Gtk.Tasque.GtkApplicationBase"/>. The
+               /// <see cref="Dispose"/> method leaves the <see cref="Gtk.Tasque.GtkApplicationBase"/> in an 
unusable state. After
+               /// calling <see cref="Dispose"/>, you must release all references to the <see 
cref="Gtk.Tasque.GtkApplicationBase"/>
+               /// so the garbage collector can reclaim the memory that the <see 
cref="Gtk.Tasque.GtkApplicationBase"/> was occupying.
+               /// </remarks>
+               public void Dispose ()
+               {
+                       Dispose (true);
+                       GC.SuppressFinalize (this);
                }
 
 #if ENABLE_NOTIFY_SHARP
-               public override void ShowAppNotification (string summary, string body)
+               public void ShowAppNotification (string summary, string body)
                {
                        var notification = new Notification (
                                summary, body, Utilities.GetIcon ("tasque", 48));
@@ -110,7 +202,7 @@ namespace Gtk.Tasque
                }
 #endif
                
-               public override void ShowPreferences ()
+               public void ShowPreferences ()
                {
                        Logger.Info ("OnPreferences called");
                        if (preferencesDialog == null) {
@@ -121,120 +213,96 @@ namespace Gtk.Tasque
                        preferencesDialog.Present ();
                }
                
-               void OnPreferencesDialogHidden (object sender, EventArgs args)
-               {
-                       preferencesDialog.Destroy ();
-                       preferencesDialog.Hidden -= OnPreferencesDialogHidden;
-                       preferencesDialog = null;
-               }
-               
-               protected override void OnBackendChanged ()
+               /// <summary>
+               /// Dispose the <see cref="Tasque.GtkApplicationBase"/>.
+               /// </summary>
+               /// <param name='disposing'>
+               /// If set to <c>true</c> this method has been invoked by the
+               /// <see cref="Dispose"/> method. Otherwise it may have been invoked by
+               /// a finalizer.
+               /// </param>
+               protected virtual void Dispose (bool disposing)
                {
-                       if (backendWasNullBeforeChange)
-                               TaskWindow.Reinitialize (!QuietStart, this);
-                       else
-                               TaskWindow.Reinitialize (true, this);
-                       
-                       Debug.WriteLine ("Configuration status: {0}", Backend.Configured.ToString ());
-                       
-                       RebuildTooltipTaskGroupModels ();
-                       if (trayIcon != null)
-                               trayIcon.RefreshTrayIconTooltip ();
+                       if (disposed)
+                               return;
+                       disposed = true;
                        
-                       base.OnBackendChanged ();
+                       if (disposing)
+                               backendManager.Dispose ();
                }
                
-               protected override void OnBackendChanging ()
-               {
-                       if (Backend != null)
-                               UnhookFromTooltipTaskGroupModels ();
-                       
-                       backendWasNullBeforeChange = Backend == null;
-                       
-                       base.OnBackendChanging ();
-               }
-
-               protected override void OnDaySwitched ()
-               {
-                       // Reinitialize window according to new date
-                       if (TaskWindow.IsOpen)
-                               TaskWindow.Reinitialize (true, this);
-                       
-                       UnhookFromTooltipTaskGroupModels ();
-                       RebuildTooltipTaskGroupModels ();
-                       if (trayIcon != null)
-                               trayIcon.RefreshTrayIconTooltip ();
-               }
-
-               protected override void OnExit (int exitCode)
-               {
-                       if (Backend != null)
-                               UnhookFromTooltipTaskGroupModels ();
-                       TaskWindow.SavePosition (Preferences);
-                       Application.Quit ();
-                       base.OnExit (exitCode);
-               }
-               
-               protected override void ShowMainWindow ()
-               {
-                       TaskWindow.ShowWindow (this);
-               }
-               
-               protected override event EventHandler RemoteInstanceKnocked;
-               
                protected void OnRemoteInstanceKnocked ()
                {
                        if (RemoteInstanceKnocked != null)
                                RemoteInstanceKnocked (this, EventArgs.Empty);
                }
 
-               void OnTooltipModelChanged (object o, EventArgs args)
+               protected abstract bool IsRemoteInstanceRunning ();
+               protected virtual void OnInitializeIdle () {}
+
+               public event EventHandler Exiting;
+               protected event EventHandler RemoteInstanceKnocked;
+
+               internal GtkTray TrayIcon { get { return trayIcon; } }
+
+               void OnPreferencesDialogHidden (object sender, EventArgs args)
                {
-                       if (trayIcon != null)
-                               trayIcon.RefreshTrayIconTooltip ();
+                       preferencesDialog.Destroy ();
+                       preferencesDialog.Hidden -= OnPreferencesDialogHidden;
+                       preferencesDialog = null;
                }
-
-               void RebuildTooltipTaskGroupModels ()
+               
+               void CheckForDaySwitch ()
                {
-                       if (Backend == null || Backend.Tasks == null) {
-                               OverdueTasks = null;
-                               TodayTasks = null;
-                               TomorrowTasks = null;
+                       if (DateTime.Today != currentDay) {
+                               Logger.Debug ("Day has changed, reloading tasks");
+                               currentDay = DateTime.Today;
                                
-                               return;
-                       }
-                       
-                       OverdueTasks = TaskGroupModelFactory.CreateOverdueModel (Backend.Tasks, Preferences);
-                       TodayTasks = TaskGroupModelFactory.CreateTodayModel (Backend.Tasks, Preferences);
-                       TomorrowTasks = TaskGroupModelFactory.CreateTomorrowModel (Backend.Tasks, 
Preferences);
-                       
-                       foreach (TaskGroupModel model in new TaskGroupModel[] { OverdueTasks, TodayTasks, 
TomorrowTasks })
-                       {
-                               if (model == null) {
-                                       continue;
-                               }
-
-                               model.CollectionChanged += OnTooltipModelChanged;
+                               // Reinitialize window according to new date
+//                             if (TaskWindow.IsOpen)
+//                                     TaskWindow.Reinitialize (true, this);
+                               
+                               if (trayIcon != null)
+                                       trayIcon.RefreshTrayIconTooltip ();
                        }
                }
-
-               void UnhookFromTooltipTaskGroupModels ()
+               
+               void ParseArgs (string[] args)
                {
-                       foreach (TaskGroupModel model in new TaskGroupModel[] { OverdueTasks, TodayTasks, 
TomorrowTasks })
-                       {
-                               if (model == null) {
-                                       continue;
-                               }
-                               
-                               model.CollectionChanged -= OnTooltipModelChanged;
+                       bool showHelp = false;
+                       var p = new OptionSet () {
+                               { "q|quiet", "hide the Tasque window upon start.",
+                                       v => quietStart = true },
+                               { "b|backend=", "the name of the {BACKEND} to use.",
+                                       v => customBackendId = v },
+                               { "h|help",  "show this message and exit.",
+                                       v => showHelp = v != null },
+                       };
+                       
+                       try {
+                               p.Parse (args);
+                       } catch (OptionException e) {
+                               Console.Write ("tasque: ");
+                               Console.WriteLine (e.Message);
+                               Console.WriteLine ("Try `tasque --help' for more information.");
+                               Exit (-1);
+                       }
+                       
+                       if (showHelp) {
+                               Console.WriteLine ("Usage: tasque [[-q|--quiet] [[-b|--backend] BACKEND]]");
+                               Console.WriteLine ();
+                               Console.WriteLine ("Options:");
+                               p.WriteOptionDescriptions (Console.Out);
+                               Exit (-1);
                        }
                }
                
-               internal GtkTray TrayIcon { get { return trayIcon; } }
-               
-               bool backendWasNullBeforeChange;
-               string confDir;
-               PreferencesDialog preferencesDialog;
+               IPreferences preferences;
+               BackendManager backendManager;
                GtkTray trayIcon;
+               PreferencesDialog preferencesDialog;
+               DateTime currentDay;
+               bool backendWasNullBeforeChange, quietStart, disposed;
+               string customBackendId;
        }
 }
diff --git a/src/Gtk.Tasque/GtkLinuxApplication.cs b/src/Gtk.Tasque/GtkLinuxApplication.cs
index a2e7403..80f4123 100644
--- a/src/Gtk.Tasque/GtkLinuxApplication.cs
+++ b/src/Gtk.Tasque/GtkLinuxApplication.cs
@@ -1,10 +1,10 @@
 // 
 // GtkLinuxApplication.cs
-//  
+// 
 // Author:
 //       Antonius Riha <antoniusriha gmail com>
 // 
-// Copyright (c) 2012 Antonius Riha
+// Copyright (c) 2012-2013 Antonius Riha
 // 
 // Permission is hereby granted, free of charge, to any person obtaining a copy
 // of this software and associated documentation files (the "Software"), to deal
@@ -31,6 +31,8 @@ namespace Gtk.Tasque
 {
        public class GtkLinuxApplication : GtkApplicationBase
        {
+               public GtkLinuxApplication (string[] args) : base (args) {}
+
                protected override void Dispose (bool disposing)
                {
                        if (disposing && remoteInstance != null)
diff --git a/src/Gtk.Tasque/GtkTray.cs b/src/Gtk.Tasque/GtkTray.cs
index f4f4ba3..9901ff1 100644
--- a/src/Gtk.Tasque/GtkTray.cs
+++ b/src/Gtk.Tasque/GtkTray.cs
@@ -4,7 +4,7 @@
 // Author:
 //       Antonius Riha <antoniusriha gmail com>
 // 
-// Copyright (c) 2012 Antonius Riha
+// Copyright (c) 2012-2013 Antonius Riha
 // 
 // Permission is hereby granted, free of charge, to any person obtaining a copy
 // of this software and associated documentation files (the "Software"), to deal
@@ -24,18 +24,18 @@
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 // THE SOFTWARE.
 using System;
+using System.Collections.Specialized;
 using System.Linq;
 using System.Text;
 using Mono.Unix;
 using Tasque;
-using Tasque.Backends;
 using Gtk;
 
 namespace Gtk.Tasque
 {
-       public abstract class GtkTray : IDisposable
+       public abstract class GtkTray
        {
-               public static GtkTray CreateTray (INativeApplication application)
+               public static GtkTray CreateTray (GtkApplicationBase application)
                {
                        var desktopSession = Environment.GetEnvironmentVariable ("DESKTOP_SESSION");
                        GtkTray tray;
@@ -55,65 +55,67 @@ namespace Gtk.Tasque
                        return tray;
                }
 
-               protected GtkTray (INativeApplication application)
+               protected GtkTray (GtkApplicationBase application)
                {
                        if (application == null)
                                throw new ArgumentNullException ("application");
                        this.application = application;
 
-                       UpdateBackend ();
-                       application.BackendChanged += HandleBackendChanged;
+                       RegisterUIManager ();
+                       
+                       application.BackendManager.BackendChanging += delegate {
+                               SwitchBackendItems (false); };
+                       application.BackendManager.BackendInitialized += delegate {
+                               SwitchBackendItems (true); };
+                       ((INotifyCollectionChanged)application.BackendManager.Tasks).CollectionChanged
+                               += delegate { RefreshTrayIconTooltip (); };
                        RefreshTrayIconTooltip ();
                }
 
-               #region IDisposable implementation
-               public void Dispose ()
-               {
-                       if (disposed)
-                               return;
-                       application.BackendChanged -= HandleBackendChanged;
-                       disposed = true;
-               }
-               #endregion
-               
                public void RefreshTrayIconTooltip ()
                {
                        var oldTooltip = Tooltip;
                        var sb = new StringBuilder ();
-                       
-                       var overdueTasks = application.OverdueTasks;
-                       if (overdueTasks != null) {
-                               int count = overdueTasks.Count ();
-
-                               if (count > 0) {
-                                       sb.Append (String.Format (Catalog.GetPluralString ("{0} task is 
Overdue\n", "{0} tasks are Overdue\n", count), count));
-                               }
+                       var tasks = application.BackendManager.Tasks;
+
+                       var overdueStart = DateTime.MinValue;
+                       var overdueEnd = DateTime.Today.AddSeconds (-1);
+                       var overdueTasks = tasks.Where (
+                               t => t.DueDate > overdueStart && t.DueDate < overdueEnd);
+                       if (overdueTasks.Any ()) {
+                               var overdueCount = overdueTasks.Count ();
+                               sb.AppendFormat (Catalog.GetPluralString ("{0} task is Overdue",
+                                   "{0} tasks are Overdue", overdueCount), overdueCount);
+                               sb.AppendLine ();
                        }
-                       
-                       var todayTasks = application.TodayTasks;
-                       if (todayTasks != null) {
-                               int count = todayTasks.Count ();
 
-                               if (count > 0) {
-                                       sb.Append (String.Format (Catalog.GetPluralString ("{0} task for 
Today\n", "{0} tasks for Today\n", count), count));
-                               }
+                       var todayEnd = DateTime.Today.AddDays (1).AddSeconds (-1);
+                       var todayTasks = tasks.Where (
+                               t => t.DueDate > DateTime.Today && t.DueDate < todayEnd);
+                       if (todayTasks.Any ()) {
+                               var todayCount = todayTasks.Count ();
+                               sb.AppendFormat (Catalog.GetPluralString ("{0} task for Today",
+                                   "{0} tasks for Today", todayCount), todayCount);
+                               sb.AppendLine ();
                        }
-                       
-                       var tomorrowTasks = application.TomorrowTasks;
-                       if (tomorrowTasks != null) {
-                               int count = tomorrowTasks.Count ();
 
-                               if (count > 0) {
-                                       sb.Append (String.Format (Catalog.GetPluralString ("{0} task for 
Tomorrow\n", "{0} tasks for Tomorrow\n", count), count));
-                               }
+                       var tomorrowStart = DateTime.Today.AddDays (1);
+                       var tomorrowEnd = DateTime.Today.AddDays (2).AddSeconds (-1);
+                       var tomorrowTasks = tasks.Where (
+                               t => t.DueDate > tomorrowStart && t.DueDate < tomorrowEnd);
+                       if (tomorrowTasks.Any ()) {
+                               var tomorrowCount = tomorrowTasks.Count ();
+                               sb.AppendFormat (Catalog.GetPluralString ("{0} task for Tomorrow",
+                                   "{0} tasks for Tomorrow", tomorrowCount), tomorrowCount);
+                               sb.AppendLine ();
                        }
 
                        if (sb.Length == 0) {
                                // Translators: This is the status icon's tooltip. When no tasks are overdue, 
due today, or due tomorrow, it displays this fun message
                                Tooltip = Catalog.GetString ("Tasque Rocks");
                        } else
-                               Tooltip = sb.ToString ().TrimEnd ('\n');
-                       
+                               Tooltip = sb.ToString ().TrimEnd (Environment.NewLine.ToCharArray ());
+
                        if (Tooltip != oldTooltip)
                                OnTooltipChanged ();
                }
@@ -121,11 +123,7 @@ namespace Gtk.Tasque
                protected string IconName { get { return "tasque-panel"; } }
                
                protected Menu Menu {
-                       get {
-                               if (uiManager == null)
-                                       RegisterUIManager ();
-                               return (Menu)uiManager.GetWidget ("/TrayIconMenu");
-                       }
+                       get { return (Menu)uiManager.GetWidget ("/TrayIconMenu"); }
                }
                
                protected Gtk.Action ToggleTaskWindowAction { get; private set; }
@@ -133,16 +131,6 @@ namespace Gtk.Tasque
                protected string Tooltip { get; private set; }
                
                protected virtual void OnTooltipChanged () {}
-               
-               void HandleBackendChanged (object sender, EventArgs e)
-               {
-                       UpdateBackend ();
-               }
-
-               void HandleBackendInitialized ()
-               {
-                       UpdateActionSensitivity ();
-               }
 
                void OnAbout (object sender, EventArgs args)
                {
@@ -156,7 +144,7 @@ namespace Gtk.Tasque
                        about.Version = Defines.Version;
                        about.Logo = Utilities.GetIcon("tasque", 48);
                        about.Copyright = Defines.CopyrightInfo;
-                       about.Comments = Catalog.GetString ("A Useful Task List");
+                       about.Comments = Catalog.GetString ("A Useful ITask List");
                        about.Website = Defines.Website;
                        about.WebsiteLabel = Catalog.GetString("Tasque Project Homepage");
                        about.Authors = authors;
@@ -169,60 +157,47 @@ namespace Gtk.Tasque
 
                void RegisterUIManager ()
                {
+                       var newTaskAction = new ActionEntry ("NewTaskAction", Stock.New,
+                           Catalog.GetString ("New ITask ..."), null, null, delegate {
+                               // Show the TaskWindow and then cause a new task to be created
+                               TaskWindow.ShowWindow (application);
+                               TaskWindow.GrabNewTaskEntryFocus (application);
+                       });
+                       
+                       var refreshAction =     new ActionEntry ("RefreshAction", Stock.Execute,
+                           Catalog.GetString ("Refresh Tasks ..."), null, null,
+                           delegate { application.BackendManager.ReInitializeBackend ();
+                       });
+                       
+                       
                        var trayActionGroup = new ActionGroup ("Tray");
                        trayActionGroup.Add (new ActionEntry [] {
-                               new ActionEntry ("NewTaskAction", Stock.New, Catalog.GetString ("New Task 
..."), null, null, delegate {
-                                       // Show the TaskWindow and then cause a new task to be created
-                                       TaskWindow.ShowWindow (application);
-                                       TaskWindow.GrabNewTaskEntryFocus (application);
-                               }),
-
+                               newTaskAction,
                                new ActionEntry ("AboutAction", Stock.About, OnAbout),
-
-                               new ActionEntry ("PreferencesAction", Stock.Preferences, delegate { 
application.ShowPreferences (); }),
-
-                               new ActionEntry ("RefreshAction", Stock.Execute, Catalog.GetString ("Refresh 
Tasks ..."),
-                                                null, null, delegate { application.Backend.Refresh(); }),
-
-                               new ActionEntry ("QuitAction", Stock.Quit, delegate { application.Exit (); })
+                               new ActionEntry ("PreferencesAction", Stock.Preferences,
+                                                delegate { application.ShowPreferences (); }),
+                               refreshAction,
+                               new ActionEntry ("QuitAction", Stock.Quit,
+                                                delegate { application.Exit (); })
                        });
                        
-                       ToggleTaskWindowAction = new Gtk.Action ("ToggleTaskWindowAction", Catalog.GetString 
("Toggle Task Window"));
+                       ToggleTaskWindowAction = new Gtk.Action ("ToggleTaskWindowAction", Catalog.GetString 
("Toggle ITask Window"));
                        ToggleTaskWindowAction.ActionGroup = trayActionGroup;
                        ToggleTaskWindowAction.Activated += delegate { TaskWindow.ToggleWindowVisible 
(application); };
                        
                        uiManager = new UIManager ();
                        uiManager.AddUiFromString (MenuXml);
                        uiManager.InsertActionGroup (trayActionGroup, 0);
-               }
-
-               void UpdateActionSensitivity ()
-               {
-                       var backend = application.Backend;
-                       var backendItemsSensitive = (backend != null && backend.Initialized);
                        
-                       if (uiManager == null)
-                               RegisterUIManager ();
-                       
-                       uiManager.GetAction ("/TrayIconMenu/NewTaskAction").Sensitive = backendItemsSensitive;
-                       uiManager.GetAction ("/TrayIconMenu/RefreshAction").Sensitive = backendItemsSensitive;
+                       SwitchBackendItems (false);
                }
 
-               void UpdateBackend ()
-               {
-                       if (backend != null)
-                               backend.BackendInitialized -= HandleBackendInitialized;
-                       backend = application.Backend;
-
-                       if (backend != null)
-                               backend.BackendInitialized += HandleBackendInitialized;
-
-                       UpdateActionSensitivity ();
+               void SwitchBackendItems (bool onOrOff) {
+                       uiManager.GetAction ("/TrayIconMenu/NewTaskAction").Sensitive = onOrOff;
+                       uiManager.GetAction ("/TrayIconMenu/RefreshAction").Sensitive = onOrOff;
                }
 
-               INativeApplication application;
-               IBackend backend;
-               bool disposed;
+               GtkApplicationBase application;
                UIManager uiManager;
                const string MenuXml = @"
 <ui>
diff --git a/src/Gtk.Tasque/GtkWinApplication.cs b/src/Gtk.Tasque/GtkWinApplication.cs
index d8b4cc3..24b1ee2 100644
--- a/src/Gtk.Tasque/GtkWinApplication.cs
+++ b/src/Gtk.Tasque/GtkWinApplication.cs
@@ -4,7 +4,7 @@
 // Author:
 //       Antonius Riha <antoniusriha gmail com>
 // 
-// Copyright (c) 2012 Antonius Riha
+// Copyright (c) 2012-2013 Antonius Riha
 // 
 // Permission is hereby granted, free of charge, to any person obtaining a copy
 // of this software and associated documentation files (the "Software"), to deal
@@ -31,7 +31,7 @@ namespace Tasque
 {
        public class GtkWinApplication : GtkApplicationBase
        {
-               public override void Initialize (string[] args)
+               public GtkWinApplication (string[] args) : base (args)
                {
                        base.Initialize (args);
 #if DEBUG
diff --git a/src/Gtk.Tasque/NoteDialog.cs b/src/Gtk.Tasque/NoteDialog.cs
index 96ce789..6d88107 100644
--- a/src/Gtk.Tasque/NoteDialog.cs
+++ b/src/Gtk.Tasque/NoteDialog.cs
@@ -4,8 +4,10 @@
 using System;
 using System.Collections.Generic;
 using Mono.Unix;
+using Tasque.Core;
+using Tasque;
 
-namespace Tasque
+namespace Gtk.Tasque
 {
        public class NoteDialog : Gtk.Dialog
        {
@@ -21,7 +23,7 @@ namespace Tasque
                {
                        this.ParentWindow = parentWindow.GdkWindow;
                        this.task = task;
-                       this.Title = String.Format(Catalog.GetString("Notes for: {0:s}"), task.Name);
+                       this.Title = String.Format(Catalog.GetString("Notes for: {0:s}"), task.Text);
                        this.HasSeparator = false;
                        this.SetSizeRequest(500,320);
                        this.Icon = Utilities.GetIcon ("tasque", 16);
@@ -46,7 +48,7 @@ namespace Tasque
                        innerEb.Show ();
                        
                        if(task.Notes != null) {
-                               foreach (INote note in task.Notes) {
+                               foreach (var note in task.Notes) {
                                        NoteWidget noteWidget = new NoteWidget (note);
                                        noteWidget.TextChanged += OnNoteTextChanged;
                                        noteWidget.DeleteButtonClicked += OnDeleteButtonClicked;
@@ -79,7 +81,7 @@ namespace Tasque
                #endregion // Constructors
                
                #region Properties
-               public ITask Task
+               public ITask ITask
                {
                        get { return task; }
                }
@@ -117,7 +119,7 @@ namespace Tasque
                {
                        NoteWidget nWidget = sender as NoteWidget;
                        try {
-                               task.DeleteNote(nWidget.Note);
+                               task.Notes.Remove (nWidget.INote);
                                targetVBox.Remove (nWidget);
                        } catch(Exception e) {
                                Logger.Debug("Unable to delete the note");
@@ -138,21 +140,14 @@ namespace Tasque
                        NoteWidget nWidget = sender as NoteWidget;
 
                        // if null, add a note, else, modify it
-                       if(nWidget.Note == null) {
+                       if(nWidget.INote == null) {
                                try {
-                                       INote note = task.CreateNote(nWidget.Text);
-                                       nWidget.Note = note;
+                                       var note = task.CreateNote (nWidget.Text);
+                                       nWidget.INote = note;
                                } catch(Exception e) {
                                        Logger.Debug("Unable to create a note");
                                        Logger.Debug(e.ToString());
                                }
-                       } else {
-                               try {
-                                       task.SaveNote(nWidget.Note);
-                               } catch(Exception e) {
-                                       Logger.Debug("Unable to save note");
-                                       Logger.Debug(e.ToString());
-                               }
                        }
                }
                #endregion // Event Handlers
diff --git a/src/Gtk.Tasque/NoteWidget.cs b/src/Gtk.Tasque/NoteWidget.cs
index 9fc06a2..49ee631 100644
--- a/src/Gtk.Tasque/NoteWidget.cs
+++ b/src/Gtk.Tasque/NoteWidget.cs
@@ -4,8 +4,10 @@
 using System;
 using Mono.Unix;
 using Gtk;
+using Tasque.Core;
+using Tasque;
 
-namespace Tasque
+namespace Gtk.Tasque
 {
        public class NoteWidget : Gtk.Notebook
        {
@@ -72,10 +74,10 @@ namespace Tasque
                #endregion // Events
                
                #region Properties
-               public INote Note
+               public INote INote
                {
                        get { return note; }
-                       set { 
+                       set {
                                note = value;
                                Text = value.Text;
                        }
diff --git a/src/Gtk.Tasque/PreferencesDialog.cs b/src/Gtk.Tasque/PreferencesDialog.cs
index 491180f..646cfb8 100644
--- a/src/Gtk.Tasque/PreferencesDialog.cs
+++ b/src/Gtk.Tasque/PreferencesDialog.cs
@@ -30,15 +30,16 @@ using System;
 using System.Collections.Generic;
 using Gtk;
 using Mono.Unix;
-using Tasque.Backends;
+using Tasque;
+using Tasque.Core;
 
-namespace Tasque
+namespace Gtk.Tasque
 {
 
        public class PreferencesDialog : Gtk.Dialog
        {
 //             private CheckButton             showCompletedTasksCheck;
-               INativeApplication application;
+               GtkApplicationBase application;
                
                Gtk.Notebook                    notebook;
                
@@ -48,12 +49,12 @@ namespace Tasque
                Gtk.Widget                              generalPage;
                int                                             generalPageId;
                Gtk.ComboBox                    backendComboBox;
-               Dictionary<int, IBackend> backendComboMap; // track backends
+               Dictionary<int, string> backendComboMap; // track backends
                int                                     selectedBackend;
                Gtk.CheckButton                 showCompletedTasksCheckButton;
-               Gtk.ListStore                   filteredCategories;
-               List<string>                    categoriesToHide;
-               Gtk.TreeView                    categoriesTree;
+               Gtk.ListStore                   filteredTaskLists;
+               List<string>                    taskListsToHide;
+               Gtk.TreeView                    taskListsTree;
 
                //
                // Appearance Page Widgets
@@ -70,7 +71,7 @@ namespace Tasque
                Gtk.Widget                              backendPage;
                int                                             backendPageId;
 
-               public PreferencesDialog (INativeApplication application) : base ()
+               public PreferencesDialog (GtkApplicationBase application) : base ()
                {
                        if (application == null)
                                throw new ArgumentNullException ("application");
@@ -134,17 +135,17 @@ namespace Tasque
                        backendPage = null;
                        backendPageId = -1;
                        
-                       if (application.Backend != null) {
-                               backendPage = (Widget)application.Backend.Preferences;
+                       var backendType = application.BackendManager.CurrentBackend;
+                       if (backendType != null) {
+                               backendPage = (Widget)application.BackendManager.GetBackendPreferencesWidget 
();
                                if (backendPage != null) {
                                        backendPage.Show ();
-                                       Label l =
-                                               new Label (GLib.Markup.EscapeText (application.Backend.Name));
+                                       var l = new Label (GLib.Markup.EscapeText (
+                                               application.BackendManager.AvailableBackends [backendType]));
                                        l.UseMarkup = false;
                                        l.UseUnderline = false;
                                        l.Show ();
-                                       backendPageId =
-                                               notebook.AppendPage (backendPage, l);
+                                       backendPageId = notebook.AppendPage (backendPage, l);
                                }
                        }
                        
@@ -240,12 +241,12 @@ namespace Tasque
                        vbox.BorderWidth = 10;
                        
                        //
-                       // Task Management System
+                       // ITask Management System
                        //
                        VBox sectionVBox = new VBox (false, 4);
                        Label l = new Label ();
                        l.Markup = string.Format ("<span size=\"large\" weight=\"bold\">{0}</span>",
-                                                                         Catalog.GetString ("Task Management 
System"));
+                                                                         Catalog.GetString ("ITask 
Management System"));
                        l.UseUnderline = false;
                        l.UseMarkup = true;
                        l.Wrap = false;
@@ -255,14 +256,14 @@ namespace Tasque
                        sectionVBox.PackStart (l, false, false, 0);
                        
                        backendComboBox = ComboBox.NewText ();
-                       backendComboMap = new Dictionary<int,IBackend> ();
+                       backendComboMap = new Dictionary<int, string> ();
                        // Fill out the ComboBox
                        int i = 0;
                        selectedBackend = -1;
-                       foreach (IBackend backend in application.AvailableBackends) {
-                               backendComboBox.AppendText (backend.Name);
-                               backendComboMap [i] = backend;
-                               if (backend == application.Backend)
+                       foreach (var backend in application.BackendManager.AvailableBackends) {
+                               backendComboBox.AppendText (backend.Value);
+                               backendComboMap [i] = backend.Key;
+                               if (backend.Key == application.BackendManager.CurrentBackend)
                                        selectedBackend = i;
                                i++;
                        }
@@ -282,12 +283,12 @@ namespace Tasque
                        vbox.PackStart (sectionVBox, false, false, 0);
                        
                        //
-                       // Task Filtering
+                       // ITask Filtering
                        //
                        sectionVBox = new VBox (false, 4);
                        l = new Label ();
                        l.Markup = string.Format ("<span size=\"large\" weight=\"bold\">{0}</span>",
-                                                                         Catalog.GetString ("Task 
Filtering"));
+                                                                         Catalog.GetString ("ITask 
Filtering"));
                        l.UseUnderline = false;
                        l.UseMarkup = true;
                        l.Wrap = false;
@@ -314,8 +315,8 @@ namespace Tasque
                        hbox.Show ();
                        innerSectionVBox.PackStart (hbox, false, false, 0);
                        
-                       // Categories TreeView
-                       l = new Label (Catalog.GetString ("Only _show these categories when \"All\" is 
selected:"));
+                       // TaskLists TreeView
+                       l = new Label (Catalog.GetString ("Only _show these lists when \"All\" is 
selected:"));
                        l.UseUnderline = true;
                        l.Xalign = 0;
                        l.Show ();
@@ -326,19 +327,19 @@ namespace Tasque
                        sw.VscrollbarPolicy = PolicyType.Automatic;
                        sw.ShadowType = ShadowType.EtchedIn;
                        
-                       categoriesTree = new TreeView ();
-                       categoriesTree.Selection.Mode = SelectionMode.None;
-                       categoriesTree.RulesHint = false;
-                       categoriesTree.HeadersVisible = false;
-                       l.MnemonicWidget = categoriesTree;
+                       taskListsTree = new TreeView ();
+                       taskListsTree.Selection.Mode = SelectionMode.None;
+                       taskListsTree.RulesHint = false;
+                       taskListsTree.HeadersVisible = false;
+                       l.MnemonicWidget = taskListsTree;
                        
                        Gtk.TreeViewColumn column = new Gtk.TreeViewColumn ();
-                       column.Title = Catalog.GetString ("Category");
+                       column.Title = Catalog.GetString ("ITask List");
                        column.Sizing = Gtk.TreeViewColumnSizing.Autosize;
                        column.Resizable = false;
                        
                        Gtk.CellRendererToggle toggleCr = new CellRendererToggle ();
-                       toggleCr.Toggled += OnCategoryToggled;
+                       toggleCr.Toggled += OnTaskListToggled;
                        column.PackStart (toggleCr, false);
                        column.SetCellDataFunc (toggleCr,
                                                new Gtk.TreeCellDataFunc (ToggleCellDataFunc));
@@ -348,10 +349,10 @@ namespace Tasque
                        column.SetCellDataFunc (textCr,
                                                new Gtk.TreeCellDataFunc (TextCellDataFunc));
                        
-                       categoriesTree.AppendColumn (column);
+                       taskListsTree.AppendColumn (column);
                        
-                       categoriesTree.Show ();
-                       sw.Add (categoriesTree);
+                       taskListsTree.Show ();
+                       sw.Add (taskListsTree);
                        sw.Show ();
                        innerSectionVBox.PackStart (sw, true, true, 0);
                        innerSectionVBox.Show ();
@@ -379,10 +380,10 @@ namespace Tasque
                private void LoadPreferences()
                {
                        Logger.Debug("Loading preferences");
-                       categoriesToHide =
-                               application.Preferences.GetStringList (PreferencesKeys.HideInAllCategory);
-                       //if (categoriesToHide == null || categoriesToHide.Count == 0)
-                       //      categoriesToHide = BuildNewCategoryList ();
+                       taskListsToHide =
+                               application.Preferences.GetStringList (PreferencesKeys.HideInAllTaskList);
+                       //if (taskListsToHide == null || taskListsToHide.Count == 0)
+                       //      taskListsToHide = BuildNewTaskListList ();
                }
 
                private void ConnectEvents()
@@ -435,30 +436,14 @@ namespace Tasque
                                }
                                
                                // if yes (replace backend)
-                               if (backendComboMap.ContainsKey (selectedBackend)) {
-                                       // Cleanup old backend
-                                       IBackend oldBackend = backendComboMap [selectedBackend];
-                                       Logger.Info ("Cleaning up '{0}'...", oldBackend.Name);
-                                       try {
-                                               oldBackend.Dispose ();
-                                       } catch (Exception e) {
-                                               Logger.Warn ("Exception cleaning up '{0}': {2}",
-                                                                        oldBackend.Name,
-                                                                        e.Message);
-                                               
-                                       }
-                                       
+                               if (backendComboMap.ContainsKey (selectedBackend))
                                        selectedBackend = -1;
-                               }
                        }
                        
-                       IBackend newBackend = null;
-                       if (backendComboMap.ContainsKey (backendComboBox.Active)) {
+                       string newBackend = null;
+                       if (backendComboMap.ContainsKey (backendComboBox.Active))
                                newBackend = backendComboMap [backendComboBox.Active];
-                       }
-                       
-                       // TODO: Set the new backend
-                       application.Backend = newBackend;
+                       application.BackendManager.SetBackend (newBackend);
                        
                        if (newBackend == null)
                                return;
@@ -466,30 +451,28 @@ namespace Tasque
                        selectedBackend = backendComboBox.Active;
                        
                        // Add a backend prefs page if one exists
-                       backendPage = (Widget)newBackend.Preferences;
+                       backendPage = (Widget)application.BackendManager.GetBackendPreferencesWidget ();
                        if (backendPage != null) {
                                backendPage.Show ();
-                               Label l = new Label (GLib.Markup.EscapeText (newBackend.Name));
+                               var l = new Label (GLib.Markup.EscapeText (
+                                       application.BackendManager.AvailableBackends [newBackend]));
                                l.UseMarkup = false;
                                l.UseUnderline = false;
                                l.Show ();
-                               backendPageId =
-                                       notebook.AppendPage (backendPage, l);
-                               
-                               // If the new backend is not configured, automatically switch
+                               backendPageId = notebook.AppendPage (backendPage, l);
+
+                               // TODO: If the new backend is not configured, automatically switch
                                // to the backend's preferences page
-                               if (!newBackend.Configured)
-                                       notebook.Page = backendPageId;
                        }
                        
                        // Save the user preference
                        application.Preferences.Set (PreferencesKeys.CurrentBackend,
                                                                                 newBackend.GetType 
().ToString ());
                        
-                       //categoriesToHide = BuildNewCategoryList ();
-                       //Application.Preferences.SetStringList (IPreferences.HideInAllCategory,
-                       //                                                                         
categoriesToHide);
-                       RebuildCategoryTree ();
+                       //taskListsToHide = BuildNewTaskListList ();
+                       //Application.Preferences.SetStringList (IPreferences.HideInAllTaskList,
+                       //                                                                         
taskListsToHide);
+                       RebuildTaskListTree ();
                }
                
                private void ToggleCellDataFunc (Gtk.TreeViewColumn column,
@@ -498,20 +481,20 @@ namespace Tasque
                                                                                         Gtk.TreeIter iter)
                {
                        Gtk.CellRendererToggle crt = cell as Gtk.CellRendererToggle;
-                       ICategory category = model.GetValue (iter, 0) as ICategory;
-                       if (category == null) {
+                       ITaskList taskList = model.GetValue (iter, 0) as ITaskList;
+                       if (taskList == null) {
                                crt.Active = true;
                                return;
                        }
                        
-                       // If the setting is null or empty, show all categories
-                       if (categoriesToHide == null || categoriesToHide.Count == 0) {
+                       // If the setting is null or empty, show all taskLists
+                       if (taskListsToHide == null || taskListsToHide.Count == 0) {
                                crt.Active = true;
                                return;
                        }
                        
-                       // Check to see if the category is specified in the list
-                       if (categoriesToHide.Contains (category.Name)) {
+                       // Check to see if the taskList is specified in the list
+                       if (taskListsToHide.Contains (taskList.Name)) {
                                crt.Active = false;
                                return;
                        }
@@ -525,47 +508,47 @@ namespace Tasque
                {
                        Gtk.CellRendererText crt = renderer as Gtk.CellRendererText;
                        crt.Ellipsize = Pango.EllipsizeMode.End;
-                       ICategory category = model.GetValue (iter, 0) as ICategory;
-                       if (category == null) {
+                       ITaskList taskList = model.GetValue (iter, 0) as ITaskList;
+                       if (taskList == null) {
                                crt.Text = string.Empty;
                                return;
                        }
                        
-                       crt.Text = GLib.Markup.EscapeText (category.Name);
+                       crt.Text = GLib.Markup.EscapeText (taskList.Name);
                }
                
-               void OnCategoryToggled (object sender, Gtk.ToggledArgs args)
+               void OnTaskListToggled (object sender, Gtk.ToggledArgs args)
                {
-                       Logger.Debug ("OnCategoryToggled");
+                       Logger.Debug ("OnTaskListToggled");
                        Gtk.TreeIter iter;
                        Gtk.TreePath path = new Gtk.TreePath (args.Path);
-                       if (!categoriesTree.Model.GetIter (out iter, path))
+                       if (!taskListsTree.Model.GetIter (out iter, path))
                                return; // Do nothing
                        
-                       ICategory category = categoriesTree.Model.GetValue (iter, 0) as ICategory;
-                       if (category == null)
+                       ITaskList taskList = taskListsTree.Model.GetValue (iter, 0) as ITaskList;
+                       if (taskList == null)
                                return;
                        
-                       //if (categoriesToHide == null)
-                       //      categoriesToHide = BuildNewCategoryList ();
+                       //if (taskListsToHide == null)
+                       //      taskListsToHide = BuildNewTaskListList ();
                        
-                       if (categoriesToHide.Contains (category.Name))
-                               categoriesToHide.Remove (category.Name);
+                       if (taskListsToHide.Contains (taskList.Name))
+                               taskListsToHide.Remove (taskList.Name);
                        else
-                               categoriesToHide.Add (category.Name);
+                               taskListsToHide.Add (taskList.Name);
                        
-                       application.Preferences.SetStringList (PreferencesKeys.HideInAllCategory,
-                                                                                                  
categoriesToHide);
+                       application.Preferences.SetStringList (PreferencesKeys.HideInAllTaskList,
+                                                                                                  
taskListsToHide);
                }
                
 /*
                /// <summary>
-               /// Build a new category list setting from all the categories
+               /// Build a new taskList list setting from all the taskLists
                /// </summary>
                /// <param name="?">
                /// A <see cref="System.String"/>
                /// </param>
-               List<string> BuildNewCategoryList ()
+               List<string> BuildNewTaskListList ()
                {
                        List<string> list = new List<string> ();
                        TreeModel model;
@@ -573,15 +556,15 @@ namespace Tasque
                        if (backend == null)
                                return list;
                        
-                       model = backend.Categories;
+                       model = backend.TaskLists;
                        Gtk.TreeIter iter;
                        if (model.GetIterFirst (out iter) == false)
                                return list;
                        
                        do {
-                               ICategory cat = model.GetValue (iter, 0) as ICategory;
-                               if (cat == null || cat is AllCategory)
-                                       continue;                               
+                               ITaskList cat = model.GetValue (iter, 0) as ITaskList;
+                               if (cat == null || cat is AllTaskList)
+                                       continue;
 
                                list.Add (cat.Name);
                        } while (model.IterNext (ref iter) == true);
@@ -590,25 +573,24 @@ namespace Tasque
                }
 */
                
-               void RebuildCategoryTree ()
+               void RebuildTaskListTree ()
                {
                        if (!backendComboMap.ContainsKey (selectedBackend)) {
-                               categoriesTree.Model = null;
+                               taskListsTree.Model = null;
                                return;
                        }
                        
-                       IBackend backend = backendComboMap [selectedBackend];
-                       filteredCategories = new ListStore (typeof (ICategory));
-                       foreach (var item in backend.Categories) {
-                               if (!(item == null || item is AllCategory))
-                                       filteredCategories.AppendValues (item);
+                       filteredTaskLists = new ListStore (typeof (ITaskList));
+                       foreach (var item in application.BackendManager.TaskLists) {
+                               if (!(item == null || item is AllList))
+                                       filteredTaskLists.AppendValues (item);
                        }
-                       categoriesTree.Model = filteredCategories;
+                       taskListsTree.Model = filteredTaskLists;
                }
                
                void OnShown (object sender, EventArgs args)
                {
-                       RebuildCategoryTree ();
+                       RebuildTaskListTree ();
                }
        }
 }
diff --git a/src/tasque/Program.cs b/src/Gtk.Tasque/Program.cs
similarity index 84%
rename from src/tasque/Program.cs
rename to src/Gtk.Tasque/Program.cs
index 8b98e39..e42c700 100644
--- a/src/tasque/Program.cs
+++ b/src/Gtk.Tasque/Program.cs
@@ -4,7 +4,7 @@
 // Author:
 //       Antonius Riha <antoniusriha gmail com>
 // 
-// Copyright (c) 2012 Antonius Riha
+// Copyright (c) 2012-2013 Antonius Riha
 // 
 // Permission is hereby granted, free of charge, to any person obtaining a copy
 // of this software and associated documentation files (the "Software"), to deal
@@ -33,19 +33,6 @@ namespace Tasque
 {
        class Program
        {
-               static INativeApplication CreateApplication ()
-               {
-                       INativeApplication nativeApp;
-#if OSX
-                       nativeApp = new OSXApplication ();
-#elif WIN32
-                       nativeApp = new GtkWinApplication ();
-#else
-                       nativeApp = new GtkLinuxApplication ();
-#endif
-                       return nativeApp;
-               }
-               
                #region Set process name
                // From Banshee: Hyena/ApplicationContext.cs
                [DllImport ("libc")] // Linux
@@ -77,13 +64,15 @@ namespace Tasque
                                lock (lockObject) {
                                        if (application != null)
                                                return;
-                                       application = CreateApplication ();
-                               }
-                                       
-                               // Fix process name not set on Unix
-                               SetProcessName ("Tasque");
 
-                               application.Initialize (args);
+                                       // Fix process name not set on Unix
+                                       SetProcessName ("Tasque");
+#if WIN
+                                       application = new GtkWinApplication (args);
+#else
+                                       application = new GtkLinuxApplication (args);
+#endif
+                               }
                        } catch (Exception e) {
                                Logger.Debug ("Exception is: {0}", e);
                                application.Exit (-1);
@@ -95,7 +84,7 @@ namespace Tasque
                        }
                }
                
-               static INativeApplication application;
+               static GtkApplicationBase application;
                static object lockObject = new object ();
        }
 }
diff --git a/src/Gtk.Tasque/Properties/AssemblyInfo.cs b/src/Gtk.Tasque/Properties/AssemblyInfo.cs
index 58b52ed..7084260 100644
--- a/src/Gtk.Tasque/Properties/AssemblyInfo.cs
+++ b/src/Gtk.Tasque/Properties/AssemblyInfo.cs
@@ -26,6 +26,6 @@
 using System.Reflection;
 using Mono.Addins;
 
-[assembly: AssemblyTitle("Gtk.Tasque")]
-[assembly: AssemblyDescription("Gtk# frontend for Tasque")]
-[assembly: AddinRoot ("GtkTasque", "0.1.13")]
+[assembly: AssemblyTitle("Tasque")]
+[assembly: AssemblyDescription("Gtk# client for Tasque")]
+[assembly: AddinRoot ("GtkTasque", "0.2.0")]
diff --git a/src/Gtk.Tasque/RemoteControl.cs b/src/Gtk.Tasque/RemoteControl.cs
index 347279e..c2104ac 100644
--- a/src/Gtk.Tasque/RemoteControl.cs
+++ b/src/Gtk.Tasque/RemoteControl.cs
@@ -10,6 +10,8 @@ using System.Linq;
 
 using Mono.Unix; // for Catalog.GetString ()
 using Tasque;
+using Tasque.Core;
+using Tasque.DateFormatters;
 
 #if ENABLE_NOTIFY_SHARP
 using Notifications;
@@ -36,7 +38,7 @@ namespace Gtk.Tasque
                        return Bus.Session.GetObject<RemoteControl> (Namespace, new ObjectPath (Path));
                }
                
-               public static RemoteControl Register (INativeApplication application)
+               public static RemoteControl Register (GtkApplicationBase application)
                {
                        BusG.Init ();
                        
@@ -49,7 +51,7 @@ namespace Gtk.Tasque
                        return remoteControl;
                }
                
-               RemoteControl (INativeApplication application)
+               RemoteControl (GtkApplicationBase application)
                {
                        if (application == null)
                                throw new ArgumentNullException ("application");
@@ -65,11 +67,11 @@ namespace Gtk.Tasque
                public System.Action RemoteInstanceKnocked { get; set; }
                                
                /// <summary>
-               /// Create a new task in Tasque using the given categoryName and name.
+               /// Create a new task in Tasque using the given taskListName and name.
                /// Will not attempt to parse due date information.
                /// </summary>
-               /// <param name="categoryName">
-               /// A <see cref="System.String"/>.  The name of an existing category.
+               /// <param name="taskListName">
+               /// A <see cref="System.String"/>.  The name of an existing taskList.
                /// Matches are not case-sensitive.
                /// </param>
                /// <param name="taskName">
@@ -84,17 +86,17 @@ namespace Gtk.Tasque
                /// A unique <see cref="System.String"/> which can be used to reference
                /// the task later.
                /// </returns>
-               public string CreateTask (string categoryName, string taskName,
+               public string CreateTask (string taskListName, string taskName,
                                                bool enterEditMode)
                {
-                       return CreateTask (categoryName, taskName, enterEditMode, false);
+                       return CreateTask (taskListName, taskName, enterEditMode, false);
                }
 
                /// <summary>
-               /// Create a new task in Tasque using the given categoryName and name.
+               /// Create a new task in Tasque using the given taskListName and name.
                /// </summary>
-               /// <param name="categoryName">
-               /// A <see cref="System.String"/>.  The name of an existing category.
+               /// <param name="taskListName">
+               /// A <see cref="System.String"/>.  The name of an existing taskList.
                /// Matches are not case-sensitive.
                /// </param>
                /// <param name="taskName">
@@ -114,30 +116,30 @@ namespace Gtk.Tasque
                /// A unique <see cref="System.String"/> which can be used to reference
                /// the task later.
                /// </returns>
-               public string CreateTask (string categoryName, string taskName,
+               public string CreateTask (string taskListName, string taskName,
                                                bool enterEditMode, bool parseDate)
                {
-                       var model = application.Backend.Categories;
+                       var model = application.BackendManager.TaskLists;
                        
                        //
                        // Validate the input parameters.  Don't allow null or empty strings
                        // be passed-in.
                        //
-                       if (categoryName == null || categoryName.Trim () == string.Empty
+                       if (taskListName == null || taskListName.Trim () == string.Empty
                                        || taskName == null || taskName.Trim () == string.Empty) {
                                return string.Empty;
                        }
                        
                        //
-                       // Look for the specified category
+                       // Look for the specified taskList
                        //
                        if (model.Count == 0) {
                                return string.Empty;
                        }
                        
-                       ICategory category = model.FirstOrDefault (c => c.Name.ToLower () == 
categoryName.ToLower ());
+                       ITaskList taskList = model.FirstOrDefault (c => c.Name.ToLower () == 
taskListName.ToLower ());
                        
-                       if (category == null) {
+                       if (taskList == null) {
                                return string.Empty;
                        }
                        
@@ -151,7 +153,8 @@ namespace Gtk.Tasque
                                                         out taskDueDate);
                        ITask task = null;
                        try {
-                               task = application.Backend.CreateTask (taskName, category);
+                               task = taskList.CreateTask (taskName);
+                               taskList.Add (task);
                                if (taskDueDate != DateTime.MinValue)
                                        task.DueDate = taskDueDate;
                        } catch (Exception e) {
@@ -164,7 +167,7 @@ namespace Gtk.Tasque
                        }
                        
                        if (enterEditMode) {
-                               TaskWindow.SelectAndEdit (task, application);
+//                             TaskWindow.SelectAndEdit (task, application);
                        }
                        
                        #if ENABLE_NOTIFY_SHARP
@@ -179,32 +182,32 @@ namespace Gtk.Tasque
                }
                
                /// <summary>
-               /// Return an array of Category names.
+               /// Return an array of ITaskList names.
                /// </summary>
                /// <returns>
                /// A <see cref="System.String"/>
                /// </returns>
-               public string[] GetCategoryNames ()
+               public string[] GetTaskListNames ()
                {
-                       List<string> categories = new List<string> ();
-                       string[] emptyArray = categories.ToArray ();
+                       List<string> taskLists = new List<string> ();
+                       string[] emptyArray = taskLists.ToArray ();
 
-                       var model = application.Backend.Categories;
+                       var model = application.BackendManager.TaskLists;
                        
                        if (model.Count == 0)
                                return emptyArray;
                        
                        foreach (var item in model) {
-                               if (!(item is AllCategory))
-                                       categories.Add (item.Name);
+                               if (!(item is AllList))
+                                       taskLists.Add (item.Name);
                        }
                        
-                       return categories.ToArray ();
+                       return taskLists.ToArray ();
                }
                
                public void ShowTasks ()
                {
-                       TaskWindow.ShowWindow (application);
+//                     TaskWindow.ShowWindow (application);
                }
                
                /// <summary>
@@ -217,7 +220,7 @@ namespace Gtk.Tasque
                public string[] GetTaskIds ()
                {
                        var ids = new List<string> ();
-                       var model = application.Backend.Tasks;
+                       var model = application.BackendManager.Tasks;
 
                        if (model.Count == 0)
                                return new string[0];
@@ -240,7 +243,7 @@ namespace Gtk.Tasque
                public string GetNameForTaskById (string id)
                {
                        ITask task = GetTaskById (id);
-                       return task != null ? task.Name : string.Empty;
+                       return task != null ? task.Text : string.Empty;
                }
                
                /// <summary>
@@ -263,58 +266,64 @@ namespace Gtk.Tasque
                        {
                                return false;
                        }
-                       task.Name = name;
+                       task.Text = name;
                        return true;
                }
-               
+
                /// <summary>
-               /// Gets the category of a task for a given ID
+               /// Gets the list of a task for a given ID
                /// </summary>
                /// <param name="id">
                /// A <see cref="System.String"/> for the ID of the task
                /// </param>
                /// <returns>
-               /// A <see cref="System.String"/> the category of the task
+               /// A <see cref="System.String"/> the list of the task
                /// </returns>
-               public string GetCategoryForTaskById (string id)
+               public string GetTaskListForTaskById (string id)
                {
-                       ITask task = GetTaskById (id);
-                       return task != null ? task.Category.Name : string.Empty;
+                       var task = GetTaskById (id);
+                       var list = application.BackendManager.TaskLists.FirstOrDefault (
+                               l => !(l is AllList) && l.Contains (task));
+                       return task != null ? list.Name : string.Empty;
                }
                
                /// <summary>
-               /// Sets the category of a task for a given ID
+               /// Sets the list of a task for a given ID
                /// </summary>
                /// <param name="id">
                /// A <see cref="System.String"/> for the ID of the task
                /// </param>
-               /// <param name="category">
-               /// A <see cref="System.String"/> the category of the task
+               /// <param name="listName">
+               /// A <see cref="System.String"/> the list of the task
                /// </param>
                /// <returns>
                /// A <see cref="System.Boolean"/>, true for success, false
                /// for failure.
                /// </returns>
-               public bool SetCategoryForTaskById (string id,
-                                                       string categoryName)
+               public bool SetTaskListForTaskById (string id,
+                       string listName)
                {
-                       ITask task = GetTaskById (id);
+                       var task = GetTaskById (id);
                        if (task == null)
-                       {
                                return false;
-                       }
 
-                       var model = application.Backend.Categories;
-                       
-                       if (model.Count == 0)
-                               return false;
-                       
-                       foreach (var item in model) {
-                               if (item.Name == categoryName) {
-                                       task.Category = item;
-                                       return true;
-                               }
+                       // NOTE: the previous data model had a one taskList to many tasks
+                       // relationship. Now it's many-to-many. However, we stick to the
+                       // old model until a general overhaul.
+                       var lists = application.BackendManager.TaskLists;
+                       var prevList = lists.FirstOrDefault (
+                               l => !(l is AllList) && l.Contains (task));
+                       var newList = lists.FirstOrDefault (
+                               l => l.Name == listName);
+
+                       if (prevList != null)
+                               prevList.Remove (task);
+
+                       if (newList != null) {
+                               newList.Add (task);
+                               return true;
                        }
+
                        return false;
                }
                
@@ -474,8 +483,10 @@ namespace Gtk.Tasque
                        ITask task = GetTaskById (id);
                        if (task == null)
                                return false;
-                               
-                       task.Delete ();
+                       
+                       var taskList = application.BackendManager.TaskLists.First (
+                               l => !(l is AllList) && l.Contains (task));
+                       taskList.Remove (task);
                        return true;
                }
                
@@ -490,10 +501,10 @@ namespace Gtk.Tasque
                /// </returns>
                private ITask GetTaskById (string id)
                {
-                       var model = application.Backend.Tasks;
+                       var model = application.BackendManager.Tasks;
                        return model.FirstOrDefault (t => t.Id == id);
                }
 
-               INativeApplication application;
+               GtkApplicationBase application;
        }
 }
diff --git a/src/Gtk.Tasque/StatusIconTray.cs b/src/Gtk.Tasque/StatusIconTray.cs
index 12e329d..6b7d953 100644
--- a/src/Gtk.Tasque/StatusIconTray.cs
+++ b/src/Gtk.Tasque/StatusIconTray.cs
@@ -30,7 +30,7 @@ namespace Gtk.Tasque
 {
        public class StatusIconTray : GtkTray
        {
-               public StatusIconTray (INativeApplication application) : base  (application)
+               public StatusIconTray (GtkApplicationBase application) : base  (application)
                {
                        tray = new StatusIcon (Utilities.GetIcon (IconName, 24));
                        tray.Visible = true;
diff --git a/src/Gtk.Tasque/TaskCalendar.cs b/src/Gtk.Tasque/TaskCalendar.cs
index 7c8707c..cf596a0 100644
--- a/src/Gtk.Tasque/TaskCalendar.cs
+++ b/src/Gtk.Tasque/TaskCalendar.cs
@@ -8,6 +8,7 @@ using System;
 using GLib;
 using Gtk;
 using Tasque;
+using Tasque.Core;
 
 namespace Tasque
 {
diff --git a/src/Gtk.Tasque/TaskGroup.cs b/src/Gtk.Tasque/TaskGroup.cs
index 378bb8a..a87134a 100644
--- a/src/Gtk.Tasque/TaskGroup.cs
+++ b/src/Gtk.Tasque/TaskGroup.cs
@@ -7,6 +7,8 @@ using System.Linq;
 using Gdk;
 using Gtk;
 using Gtk.Tasque;
+using Tasque.Core;
+using Tasque.Utils;
 
 namespace Tasque
 {
@@ -27,7 +29,7 @@ namespace Tasque
                
                #region Constructor
                public TaskGroup (string groupName, DateTime rangeStart,
-                                 DateTime rangeEnd, ICollection<ITask> tasks, INativeApplication application)
+                                 DateTime rangeEnd, ICollection<ITask> tasks, GtkApplicationBase application)
                {
                        if (application == null)
                                throw new ArgumentNullException ("application");
@@ -192,9 +194,9 @@ namespace Tasque
                #endregion // Public Properties
                
                #region Public Methods
-               public void Refilter (ICategory selectedCategory)
+               public void Refilter (ITaskList selectedTaskList)
                {
-                       taskView.Refilter (selectedCategory);
+                       taskView.Refilter (selectedTaskList);
                }
                
                /// <summary>
@@ -320,7 +322,7 @@ namespace Tasque
                #endregion // Methods
                
                #region Private Methods
-               protected INativeApplication Application { get; private set; }
+               protected GtkApplicationBase Application { get; private set; }
 
                protected TaskGroupModel Model { get; set; }
 
@@ -350,37 +352,37 @@ namespace Tasque
                }
                
                /// <summary>
-               /// Refilter the hard way by discovering the category to filter on
+               /// Refilter the hard way by discovering the taskList to filter on
                /// </summary>
                private void Refilter ()
                {
-                       ICategory cat = GetSelectedCategory ();
+                       ITaskList cat = GetSelectedTaskList ();
                        if (cat != null)
                                Refilter (cat);
                }
                
                /// <summary>
-               /// This returns the currently selected category.
+               /// This returns the currently selected taskList.
                /// TODO: This should really be moved as a method Application or
                /// or something.
                /// </summary>
                /// <returns>
-               /// A <see cref="ICategory"/>
+               /// A <see cref="ITaskList"/>
                /// </returns>
-               private ICategory GetSelectedCategory ()
+               private ITaskList GetSelectedTaskList ()
                {
                        // TODO: Move this code into some function in the backend/somewhere
-                       // with the signature of GetCategoryForName (string catName):ICategory
-                       string selectedCategoryName =
-                               Application.Preferences.Get (PreferencesKeys.SelectedCategoryKey);
+                       // with the signature of GetTaskListForName (string catName):ITaskList
+                       string selectedTaskListName =
+                               Application.Preferences.Get (PreferencesKeys.SelectedTaskListKey);
                        
-                       ICategory category = null;
-                       if (selectedCategoryName != null) {
-                               var model = Application.Backend.Categories;
-                               category = model.FirstOrDefault (c => c != null && c.Name == 
selectedCategoryName);
+                       ITaskList taskList = null;
+                       if (selectedTaskListName != null) {
+                               var model = Application.BackendManager.TaskLists;
+                               taskList = model.FirstOrDefault (c => c != null && c.Name == 
selectedTaskListName);
                        }
                        
-                       return category;
+                       return taskList;
                }
                
                /// <summary>
diff --git a/src/Gtk.Tasque/TaskRowEditingEventArgs.cs b/src/Gtk.Tasque/TaskRowEditingEventArgs.cs
index bbd12f1..dabebca 100644
--- a/src/Gtk.Tasque/TaskRowEditingEventArgs.cs
+++ b/src/Gtk.Tasque/TaskRowEditingEventArgs.cs
@@ -25,6 +25,7 @@
 // THE SOFTWARE.
 using System;
 using Tasque;
+using Tasque.Core;
 
 namespace Gtk.Tasque
 {
@@ -34,7 +35,7 @@ namespace Gtk.Tasque
                {
                        if (task == null)
                                throw new ArgumentNullException ("task");
-                       Task = task;
+                       ITask = task;
                        if (path == null)
                                throw new ArgumentNullException ("path");
                        Path = path;
@@ -43,6 +44,6 @@ namespace Gtk.Tasque
                
                public TreeIter Iter { get; private set; }
                public TreePath Path { get; private set; }
-               public ITask Task { get; private set; }
+               public ITask ITask { get; private set; }
        }
 }
diff --git a/src/Gtk.Tasque/TaskView.cs b/src/Gtk.Tasque/TaskView.cs
index c6ad1c3..cc2750f 100644
--- a/src/Gtk.Tasque/TaskView.cs
+++ b/src/Gtk.Tasque/TaskView.cs
@@ -8,6 +8,7 @@ using System.Linq;
 using Mono.Addins;
 using Tasque;
 using Gtk;
+using Tasque.Core;
 
 namespace Gtk.Tasque
 {
@@ -20,7 +21,7 @@ namespace Gtk.Tasque
        public class TaskView
        {
                private Gtk.TreeModelFilter modelFilter;
-               private ICategory filterCategory;       
+               private ITaskList filterTaskList;
                
                public event EventHandler NumberOfTasksChanged;
 
@@ -48,7 +49,7 @@ namespace Gtk.Tasque
                        // to select it and THEN have to click on the column item they want
                        // to modify.
                        
-                       filterCategory = null;
+                       filterTaskList = null;
                        
                        modelFilter = new Gtk.TreeModelFilter (model, null);
                        modelFilter.VisibleFunc = FilterFunc;
@@ -81,7 +82,7 @@ namespace Gtk.Tasque
                                        if (rowEditingDictionary.IsEmpty)
                                                IsTaskBeingEdited = true;
                                        
-                                       if (!rowEditingDictionary.Any (v => v.Value.Task == e.Task)) {
+                                       if (!rowEditingDictionary.Any (v => v.Value.ITask == e.ITask)) {
                                                if (RowEditingStarted != null)
                                                        RowEditingStarted (this, e);
                                        }
@@ -91,7 +92,7 @@ namespace Gtk.Tasque
                                col.CellEditingFinished += (sender, e) => {
                                        TaskRowEditingEventArgs args;
                                        rowEditingDictionary.TryRemove ((ITaskColumn)sender, out args);
-                                       if (!rowEditingDictionary.Any (v => v.Value == e.Task)) {
+                                       if (!rowEditingDictionary.Any (v => v.Value.ITask == e.ITask)) {
                                                if (RowEditingFinished != null)
                                                        RowEditingFinished (this, e);
                                        }
@@ -113,12 +114,12 @@ namespace Gtk.Tasque
                #region Public Methods
                public void Refilter ()
                {
-                       Refilter (filterCategory);
+                       Refilter (filterTaskList);
                }
                
-               public void Refilter (ICategory selectedCategory)
+               public void Refilter (ITaskList selectedTaskList)
                {
-                       this.filterCategory = selectedCategory;
+                       this.filterTaskList = selectedTaskList;
                        TreeView.Model = modelFilter;
                        modelFilter.Refilter ();
                }
@@ -171,9 +172,9 @@ namespace Gtk.Tasque
                        List<String> list = new List<String>();
        
                        if(TreeView.Selection.GetSelected(out m, out iter)) {
-                               ITask task = Model.GetValue (iter, 0) as ITask;                               
                        
+                               ITask task = Model.GetValue (iter, 0) as ITask;
                                if (task != null && task.HasNotes && task.Notes != null) {
-                                       foreach (INote note in task.Notes) {
+                                       foreach (var note in task.Notes) {
                                                // for the tooltip, truncate any notes longer than 250 
characters.
                                                if (note.Text.Length > toolTipMaxLength)
                                                        list.Add(note.Text.Substring(0, toolTipMaxLength - 
snipText.Length) + 
@@ -217,15 +218,15 @@ namespace Gtk.Tasque
                                return false;
                        }
                        
-                       if (task.State == TaskState.Deleted) {
+                       if (task.State == TaskState.Discarded) {
                                //Logger.Debug ("TaskTreeView.FilterFunc:\n\t{0}\n\t{1}\n\tReturning false", 
task.Name, task.State);  
                                return false;
                        }
                        
-                       if (filterCategory == null)
+                       if (filterTaskList == null)
                                return true;
                        
-                       return filterCategory.ContainsTask (task);
+                       return filterTaskList.Contains (task);
                }
                #endregion // Private Methods
                
diff --git a/src/Gtk.Tasque/TaskWindow.cs b/src/Gtk.Tasque/TaskWindow.cs
index b6bd96b..dc17061 100644
--- a/src/Gtk.Tasque/TaskWindow.cs
+++ b/src/Gtk.Tasque/TaskWindow.cs
@@ -36,25 +36,25 @@ using Gdk;
 using Gtk;
 using Mono.Unix;
 using Tasque;
-using Tasque.Backends;
+using Tasque.Core;
+using Tasque.DateFormatters;
 
 namespace Gtk.Tasque
 {
        public class TaskWindow : Gtk.Window 
        {
-               INativeApplication application;
+               GtkApplicationBase application;
 
                private static TaskWindow taskWindow = null;
                private static int lastXPos;
                private static int lastYPos;
                private static Gdk.Pixbuf noteIcon;
                
-               private IBackend backend;
                private ScrolledWindow scrolledWindow;
                
                private Entry addTaskEntry;
                private MenuToolButton addTaskButton;
-               private Gtk.ComboBox categoryComboBox;
+               private Gtk.ComboBox taskListComboBox;
                private Gtk.VBox targetVBox;
                
                private TaskGroup overdueGroup;
@@ -87,13 +87,12 @@ namespace Gtk.Tasque
                        noteIcon = Utilities.GetIcon ("tasque-note", 16);
                }
                
-               public TaskWindow (IBackend aBackend, INativeApplication application) : base 
(Gtk.WindowType.Toplevel)
+               public TaskWindow (GtkApplicationBase application) : base (Gtk.WindowType.Toplevel)
                {
                        if (application == null)
                                throw new ArgumentNullException ("application");
                        this.application = application;
 
-                       this.backend = aBackend;
                        taskGroups = new List<TaskGroup> ();
                        noteDialogs = new Dictionary<ITask, NoteDialog> ();
                        InitWindow();
@@ -132,22 +131,22 @@ namespace Gtk.Tasque
                        HBox topHBox = new HBox (false, 0);
                        topHBox.BorderWidth = 4;
                        
-                       categoryComboBox = new ComboBox ();
-                       categoryComboBox.Accessible.Description = "Category Selection";
-                       categoryComboBox.WidthRequest = 150;
-                       categoryComboBox.WrapWidth = 1;
-                       categoryComboBox.Sensitive = false;
+                       taskListComboBox = new ComboBox ();
+                       taskListComboBox.Accessible.Description = "ITaskList Selection";
+                       taskListComboBox.WidthRequest = 150;
+                       taskListComboBox.WrapWidth = 1;
+                       taskListComboBox.Sensitive = false;
                        CellRendererText comboBoxRenderer = new Gtk.CellRendererText ();
                        comboBoxRenderer.WidthChars = 20;
                        comboBoxRenderer.Ellipsize = Pango.EllipsizeMode.End;
-                       categoryComboBox.PackStart (comboBoxRenderer, true);
-                       categoryComboBox.SetCellDataFunc (comboBoxRenderer,
-                               new Gtk.CellLayoutDataFunc (CategoryComboBoxDataFunc));
+                       taskListComboBox.PackStart (comboBoxRenderer, true);
+                       taskListComboBox.SetCellDataFunc (comboBoxRenderer,
+                               new Gtk.CellLayoutDataFunc (TaskListComboBoxDataFunc));
                        
-                       categoryComboBox.Show ();
-                       topHBox.PackStart (categoryComboBox, false, false, 0);
+                       taskListComboBox.Show ();
+                       topHBox.PackStart (taskListComboBox, false, false, 0);
                        
-                       // Space the addTaskButton and the categoryComboBox
+                       // Space the addTaskButton and the taskListComboBox
                        // far apart by using a blank label that expands
                        Label spacer = new Label (string.Empty);
                        spacer.Show ();
@@ -175,7 +174,7 @@ namespace Gtk.Tasque
                        buttonHBox.PackStart (l, true, true, 0);
                        buttonHBox.Show ();
                        addTaskButton = 
-                               new MenuToolButton (buttonHBox, Catalog.GetString ("_Add Task"));
+                               new MenuToolButton (buttonHBox, Catalog.GetString ("_Add ITask"));
                        addTaskButton.UseUnderline = true;
                        // Disactivate the button until the backend is initialized
                        addTaskButton.Sensitive = false;
@@ -237,13 +236,9 @@ namespace Gtk.Tasque
                        Shown += OnWindowShown;
                        DeleteEvent += WindowDeleted;
                        
-                       backend.BackendInitialized += OnBackendInitialized;
-                       backend.BackendSyncStarted += OnBackendSyncStarted;
-                       backend.BackendSyncFinished += OnBackendSyncFinished;
-                       // if the backend is already initialized, go ahead... initialize
-                       if(backend.Initialized) {
-                               OnBackendInitialized();
-                       }
+                       application.BackendManager.BackendInitialized += OnBackendInitialized;
+                       // FIXME: if the backend is already initialized, go ahead... initialize
+                       OnBackendInitialized (null, null);
                        
                        application.Preferences.SettingChanged += OnSettingChanged;
                }
@@ -263,9 +258,8 @@ namespace Gtk.Tasque
                        rangeEnd = new DateTime (rangeEnd.Year, rangeEnd.Month, rangeEnd.Day,
                                                                         23, 59, 59);
                        
-                       overdueGroup = new TaskGroup (Catalog.GetString ("Overdue"),
-                                                                                 rangeStart, rangeEnd,
-                                                                                 backend.Tasks, application);
+                       overdueGroup = new TaskGroup (Catalog.GetString ("Overdue"), rangeStart, rangeEnd,
+                                                                                 
application.BackendManager.Tasks, application);
                        overdueGroup.RowActivated += OnRowActivated;
                        overdueGroup.ButtonPressed += OnButtonPressed;
                        overdueGroup.Show ();
@@ -281,9 +275,8 @@ namespace Gtk.Tasque
                        rangeEnd = DateTime.Now;
                        rangeEnd = new DateTime (rangeEnd.Year, rangeEnd.Month,
                                                                         rangeEnd.Day, 23, 59, 59);
-                       todayGroup = new TaskGroup (Catalog.GetString ("Today"),
-                                                                               rangeStart, rangeEnd,
-                                                                               backend.Tasks, application);
+                       todayGroup = new TaskGroup (Catalog.GetString ("Today"), rangeStart, rangeEnd,
+                                                                               
application.BackendManager.Tasks, application);
                        todayGroup.RowActivated += OnRowActivated;
                        todayGroup.ButtonPressed += OnButtonPressed;
                        todayGroup.Show ();
@@ -299,11 +292,10 @@ namespace Gtk.Tasque
                        rangeEnd = DateTime.Now.AddDays (1);
                        rangeEnd = new DateTime (rangeEnd.Year, rangeEnd.Month,
                                                                         rangeEnd.Day, 23, 59, 59);
-                       tomorrowGroup = new TaskGroup (Catalog.GetString ("Tomorrow"),
-                                                                                  rangeStart, rangeEnd,
-                                                                                  backend.Tasks, 
application);
+                       tomorrowGroup = new TaskGroup (Catalog.GetString ("Tomorrow"), rangeStart, rangeEnd,
+                                                                                  
application.BackendManager.Tasks, application);
                        tomorrowGroup.RowActivated += OnRowActivated;
-                       tomorrowGroup.ButtonPressed += OnButtonPressed;                 
+                       tomorrowGroup.ButtonPressed += OnButtonPressed;
                        tomorrowGroup.Show ();
                        targetVBox.PackStart (tomorrowGroup, false, false, 0);
                        taskGroups.Add (tomorrowGroup);
@@ -317,11 +309,11 @@ namespace Gtk.Tasque
                        rangeEnd = DateTime.Now.AddDays (6);
                        rangeEnd = new DateTime (rangeEnd.Year, rangeEnd.Month,
                                                                         rangeEnd.Day, 23, 59, 59);
-                       nextSevenDaysGroup = new TaskGroup (Catalog.GetString ("Next 7 Days"),
-                                                                                  rangeStart, rangeEnd,
-                                                                                  backend.Tasks, 
application);
+                       nextSevenDaysGroup = new TaskGroup (Catalog.GetString ("Next 7 Days"), rangeStart,
+                                                           rangeEnd, application.BackendManager.Tasks,
+                                                           application);
                        nextSevenDaysGroup.RowActivated += OnRowActivated;
-                       nextSevenDaysGroup.ButtonPressed += OnButtonPressed;                            
+                       nextSevenDaysGroup.ButtonPressed += OnButtonPressed;
                        nextSevenDaysGroup.Show ();
                        targetVBox.PackStart (nextSevenDaysGroup, false, false, 0);
                        taskGroups.Add (nextSevenDaysGroup);
@@ -333,11 +325,10 @@ namespace Gtk.Tasque
                        rangeStart = new DateTime (rangeStart.Year, rangeStart.Month,
                                                                           rangeStart.Day, 0, 0, 0);
                        rangeEnd = DateTime.MaxValue;
-                       futureGroup = new TaskGroup (Catalog.GetString ("Future"),
-                                                                                rangeStart, rangeEnd,
-                                                                                backend.Tasks, application);
+                       futureGroup = new TaskGroup (Catalog.GetString ("Future"), rangeStart, rangeEnd,
+                                                                                
application.BackendManager.Tasks, application);
                        futureGroup.RowActivated += OnRowActivated;
-                       futureGroup.ButtonPressed += OnButtonPressed;                   
+                       futureGroup.ButtonPressed += OnButtonPressed;
                        futureGroup.Show ();
                        targetVBox.PackStart (futureGroup, false, false, 0);
                        taskGroups.Add (futureGroup);
@@ -347,10 +338,10 @@ namespace Gtk.Tasque
                        //
                        rangeStart = DateTime.MinValue;
                        rangeEnd = DateTime.MaxValue;
-                       completedTaskGroup = new CompletedTaskGroup (
-                                       Catalog.GetString ("Completed"),
-                                       rangeStart, rangeEnd,
-                                       backend.Tasks, application);
+                       completedTaskGroup = new CompletedTaskGroup (Catalog.GetString ("Completed"),
+                                                                    rangeStart, rangeEnd,
+                                                                    application.BackendManager.Tasks,
+                                                                    application);
                        completedTaskGroup.RowActivated += OnRowActivated;
                        completedTaskGroup.ButtonPressed += OnButtonPressed;
                        completedTaskGroup.Show ();
@@ -365,27 +356,27 @@ namespace Gtk.Tasque
                        
                        // Set up the combo box (after the above to set the current filter)
 
-                       var categoryComboStore = new ListStore (typeof(ICategory));
-                       foreach (var item in application.Backend.Categories) {
-                               categoryComboStore.AppendValues (item);
+                       var taskListComboStore = new ListStore (typeof(ITaskList));
+                       foreach (var item in application.BackendManager.TaskLists) {
+                               taskListComboStore.AppendValues (item);
                        }
                        
-                       categoryComboBox.Model = categoryComboStore;
+                       taskListComboBox.Model = taskListComboStore;
 
-                       // Read preferences for the last-selected category and select it
-                       string selectedCategoryName =
-                               application.Preferences.Get (PreferencesKeys.SelectedCategoryKey);
+                       // Read preferences for the last-selected taskList and select it
+                       string selectedTaskListName =
+                               application.Preferences.Get (PreferencesKeys.SelectedTaskListKey);
                        
-                       categoryComboBox.Changed += OnCategoryChanged;
+                       taskListComboBox.Changed += OnTaskListChanged;
                        
-                       SelectCategory (selectedCategoryName);
+                       SelectTaskList (selectedTaskListName);
                }
                
                #region Public Methods
                /// <summary>
-               /// Method to allow other classes to "click" on the "Add Task" button.
+               /// Method to allow other classes to "click" on the "Add ITask" button.
                /// </summary>
-               public static void AddTask (INativeApplication application)
+               public static void AddTask (GtkApplicationBase application)
                {
                        if (taskWindow == null)
                                TaskWindow.ShowWindow (application);
@@ -415,17 +406,17 @@ namespace Gtk.Tasque
 
                }
                
-               public static void ShowWindow (INativeApplication application)
+               public static void ShowWindow (GtkApplicationBase application)
                {
                        ShowWindow (false, application);
                }
                
-               public static void ToggleWindowVisible (INativeApplication application)
+               public static void ToggleWindowVisible (GtkApplicationBase application)
                {
                        ShowWindow (true, application);
                }
                
-               private static void ShowWindow (bool supportToggle, INativeApplication application)
+               private static void ShowWindow (bool supportToggle, GtkApplicationBase application)
                {
                        if(taskWindow != null) {
                                if(taskWindow.IsActive && supportToggle) {
@@ -448,8 +439,8 @@ namespace Gtk.Tasque
                                        }
                                        taskWindow.Present();
                                }
-                       } else if (application.Backend != null) {
-                               TaskWindow.taskWindow = new TaskWindow (application.Backend, application);
+                       } else if (application.BackendManager.CurrentBackend != null) {
+                               taskWindow = new TaskWindow (application);
                                if(lastXPos == 0 || lastYPos == 0)
                                {
                                        lastXPos = application.Preferences.GetInt("MainWindowLastXPos");
@@ -466,7 +457,7 @@ namespace Gtk.Tasque
                        }
                }
                
-               public static void GrabNewTaskEntryFocus (INativeApplication application)
+               public static void GrabNewTaskEntryFocus (GtkApplicationBase application)
                {
                        if (taskWindow == null)
                                TaskWindow.ShowWindow (application);
@@ -474,7 +465,7 @@ namespace Gtk.Tasque
                        taskWindow.addTaskEntry.GrabFocus ();
                }
                
-               public static void SelectAndEdit (ITask task, INativeApplication application)
+               public static void SelectAndEdit (ITask task, GtkApplicationBase application)
                {
                        ShowWindow (application);
                        taskWindow.EnterEditMode (task, true);
@@ -532,7 +523,7 @@ namespace Gtk.Tasque
                /// <summary>
                /// This should be called after a new IBackend has been set
                /// </summary>
-               public static void Reinitialize (bool show, INativeApplication application)
+               public static void Reinitialize (bool show, GtkApplicationBase application)
                {
                        if (TaskWindow.taskWindow != null) {
                                TaskWindow.taskWindow.Hide ();
@@ -551,7 +542,7 @@ namespace Gtk.Tasque
                        // Make sure we've waited around for the new task to fully
                        // be added to the TreeModel before continuing.  Some
                        // backends might be threaded and will have used something
-                       // like Gtk.Idle.Add () to actually store the new Task in
+                       // like Gtk.Idle.Add () to actually store the new ITask in
                        // their TreeModel.
                        while (Gtk.Application.EventsPending ())
                                Gtk.Application.RunIteration ();
@@ -579,7 +570,7 @@ namespace Gtk.Tasque
                        // Make sure we've waited around for the new task to fully
                        // be added to the TreeModel before continuing.  Some
                        // backends might be threaded and will have used something
-                       // like Gtk.Idle.Add () to actually store the new Task in
+                       // like Gtk.Idle.Add () to actually store the new ITask in
                        // their TreeModel.
                        while (Gtk.Application.EventsPending ())
                                Gtk.Application.RunIteration ();
@@ -589,7 +580,7 @@ namespace Gtk.Tasque
                        // Make sure we've waited around for the new task to fully
                        // be added to the TreeModel before continuing.  Some
                        // backends might be threaded and will have used something
-                       // like Gtk.Idle.Add () to actually store the new Task in
+                       // like Gtk.Idle.Add () to actually store the new ITask in
                        // their TreeModel.
                        while (Gtk.Application.EventsPending ())
                                Gtk.Application.RunIteration ();
@@ -644,34 +635,34 @@ namespace Gtk.Tasque
                #endregion // Public Methods
                
                #region Private Methods
-               void CategoryComboBoxDataFunc (Gtk.CellLayout layout,
+               void TaskListComboBoxDataFunc (Gtk.CellLayout layout,
                                                                           Gtk.CellRenderer renderer,
                                                                           Gtk.TreeModel model,
                                                                           Gtk.TreeIter iter)
                {
                        Gtk.CellRendererText crt = renderer as Gtk.CellRendererText;
-                       ICategory category = model.GetValue (iter, 0) as ICategory;
+                       ITaskList taskList = model.GetValue (iter, 0) as ITaskList;
 
                        // CRG: What?  I added this check for null and we don't crash
                        // but I never see anything called unknown
-                       if(category != null && category.Name != null) {
+                       if(taskList != null && taskList.Name != null) {
                                crt.Text =
                                        string.Format ("{0} ({1})",
-                                                                  category.Name,
-                                                                  GetTaskCountInCategory (category));
+                                                                  taskList.Name,
+                                                                  GetTaskCountInTaskList (taskList));
                        } else
                                crt.Text = "unknown";
                }
                
-               // TODO: Move this method into a property of ICategory.TaskCount
-               private int GetTaskCountInCategory (ICategory category)
+               // TODO: Move this method into a property of ITaskList.TaskCount
+               private int GetTaskCountInTaskList (ITaskList taskList)
                {
                        // This is disgustingly inefficient, but, oh well
                        int count = 0;
-                       var model = application.Backend.Tasks;
+                       var model = application.BackendManager.Tasks;
                        count = model.Count (t => t != null &&
                                             t.State == TaskState.Active &&
-                                            category.ContainsTask (t));
+                                            taskList.Contains (t));
                        return count;
                }
                
@@ -693,7 +684,7 @@ namespace Gtk.Tasque
                        // Make sure we've waited around for the new task to fully
                        // be added to the TreeModel before continuing.  Some
                        // backends might be threaded and will have used something
-                       // like Gtk.Idle.Add () to actually store the new Task in
+                       // like Gtk.Idle.Add () to actually store the new ITask in
                        // their TreeModel.
                        while (Gtk.Application.EventsPending ())
                                Gtk.Application.RunIteration ();
@@ -714,15 +705,15 @@ namespace Gtk.Tasque
                        }
                }
                
-               private void RebuildAddTaskMenu (ICollection<ICategory> categoriesModel)
+               private void RebuildAddTaskMenu (ICollection<ITaskList> taskListsModel)
                {
                        Gtk.Menu menu = new Menu ();
                        
-                       foreach (var cat in categoriesModel) {
-                               if (cat is AllCategory)
+                       foreach (var cat in taskListsModel) {
+                               if (cat is AllList)
                                        continue;
-                               var item = new CategoryMenuItem (cat);
-                               item.Activated += OnNewTaskByCategory;
+                               var item = new TaskListMenuItem (cat);
+                               item.Activated += OnNewTaskByTaskList;
                                item.ShowAll ();
                                menu.Add (item);
                        }
@@ -730,37 +721,37 @@ namespace Gtk.Tasque
                        addTaskButton.Menu = menu;
                }
                
-               private void SelectCategory (string categoryName)
+               private void SelectTaskList (string taskListName)
                {
                        Gtk.TreeIter iter;
-                       Gtk.TreeModel model = categoryComboBox.Model;
-                       bool categoryWasSelected = false;
+                       Gtk.TreeModel model = taskListComboBox.Model;
+                       bool taskListWasSelected = false;
 
-                       if (categoryName != null) {
+                       if (taskListName != null) {
                                // Iterate through (yeah, I know this is gross!) and find the
-                               // matching category
+                               // matching taskList
                                if (model.GetIterFirst (out iter)) {
                                        do {
-                                               ICategory cat = model.GetValue (iter, 0) as ICategory;
+                                               ITaskList cat = model.GetValue (iter, 0) as ITaskList;
                                                if (cat == null)
                                                        continue; // Needed for some reason to prevent 
crashes from some backends
-                                               if (cat.Name.CompareTo (categoryName) == 0) {
-                                                       categoryComboBox.SetActiveIter (iter);
-                                                       categoryWasSelected = true;
+                                               if (cat.Name.CompareTo (taskListName) == 0) {
+                                                       taskListComboBox.SetActiveIter (iter);
+                                                       taskListWasSelected = true;
                                                        break;
                                                }
                                        } while (model.IterNext (ref iter));
                                }
                        }
                        
-                       if (!categoryWasSelected) {
+                       if (!taskListWasSelected) {
                                // Select the first item in the list (which should be the "All"
-                               // category.
+                               // taskList.
                                if (model.GetIterFirst (out iter)) {
-                                       // Make sure we can actually get a category
-                                       ICategory cat = model.GetValue (iter, 0) as ICategory;
+                                       // Make sure we can actually get a taskList
+                                       ITaskList cat = model.GetValue (iter, 0) as ITaskList;
                                        if (cat != null)
-                                               categoryComboBox.SetActiveIter (iter);
+                                               taskListComboBox.SetActiveIter (iter);
                                }
                        }
                }
@@ -782,9 +773,10 @@ namespace Gtk.Tasque
                        dialog.Present ();
                }
                
-               private ITask CreateTask (string taskText, ICategory category)
+               private ITask CreateTask (string taskText, ITaskList taskList)
                {
-                       ITask task = backend.CreateTask (taskText, category);
+                       var task = taskList.CreateTask (taskText);
+                       taskList.Add (task);
                        
                        if (task == null) {
                                Logger.Debug ("Error creating a new task!");
@@ -793,7 +785,7 @@ namespace Gtk.Tasque
                                TaskWindow.ShowStatus (status);
                        } else {
                                // Show successful status
-                               status = Catalog.GetString ("Task created successfully");       
+                               status = Catalog.GetString ("ITask created successfully");      
                                TaskWindow.ShowStatus (status);
                                // Clear out the entry
                                addTaskEntry.Text = string.Empty;
@@ -867,10 +859,10 @@ namespace Gtk.Tasque
                
                void OnSettingChanged (IPreferences preferences, string settingKey)
                {
-                       if (settingKey.CompareTo (PreferencesKeys.HideInAllCategory) != 0)
+                       if (settingKey.CompareTo (PreferencesKeys.HideInAllTaskList) != 0)
                                return;
                        
-                       OnCategoryChanged (this, EventArgs.Empty);
+                       OnTaskListChanged (this, EventArgs.Empty);
                }
                
                void OnGrabEntryFocus (object sender, EventArgs args)
@@ -932,11 +924,11 @@ namespace Gtk.Tasque
                                return;
                        
                        Gtk.TreeIter iter;
-                       if (!categoryComboBox.GetActiveIter (out iter))
+                       if (!taskListComboBox.GetActiveIter (out iter))
                                return;
                        
-                       ICategory category =
-                               categoryComboBox.Model.GetValue (iter, 0) as ICategory;
+                       ITaskList taskList =
+                               taskListComboBox.Model.GetValue (iter, 0) as ITaskList;
                
                        // If enabled, attempt to parse due date information
                        // out of the entered task text.
@@ -950,7 +942,7 @@ namespace Gtk.Tasque
                        else
                                taskName = enteredTaskText;
                        
-                       ITask task = CreateTask (taskName, category);
+                       ITask task = CreateTask (taskName, taskList);
                        if (task == null)
                                return; // TODO: Explain error to user!
                        
@@ -960,67 +952,67 @@ namespace Gtk.Tasque
                        HighlightTask (task);
                }
                
-               void OnNewTaskByCategory (object sender, EventArgs args)
+               void OnNewTaskByTaskList (object sender, EventArgs args)
                {
                        string newTaskText = addTaskEntry.Text.Trim ();
                        if (newTaskText.Length == 0)
                                return;
                        
-                       CategoryMenuItem item = sender as CategoryMenuItem;
+                       TaskListMenuItem item = sender as TaskListMenuItem;
                        if (item == null)
                                return;
                        
-                       // Determine if the selected category is currently shown in the
+                       // Determine if the selected taskList is currently shown in the
                        // task window.  If we're in a specific cateogory or on the All
-                       // category and the selected category is not showing, we've got
-                       // to switch the category first so the user will be able to edit
+                       // taskList and the selected taskList is not showing, we've got
+                       // to switch the taskList first so the user will be able to edit
                        // the title of the task.
                        Gtk.TreeIter iter;
-                       if (categoryComboBox.GetActiveIter (out iter)) {
-                               ICategory selectedCategory =
-                                       categoryComboBox.Model.GetValue (iter, 0) as ICategory;
+                       if (taskListComboBox.GetActiveIter (out iter)) {
+                               ITaskList selectedTaskList =
+                                       taskListComboBox.Model.GetValue (iter, 0) as ITaskList;
                                
                                // Check to see if "All" is selected
-                               if (selectedCategory is AllCategory) {
-                                       // See if the item.Category is currently being shown in
-                                       // the "All" category and if not, select the category
+                               if (selectedTaskList is AllList) {
+                                       // See if the item.ITaskList is currently being shown in
+                                       // the "All" taskList and if not, select the taskList
                                        // specifically.
-                                       List<string> categoriesToHide =
+                                       List<string> taskListsToHide =
                                                application.Preferences.GetStringList (
-                                                       PreferencesKeys.HideInAllCategory);
-                                       if (categoriesToHide != null && categoriesToHide.Contains 
(item.Category.Name)) {
-                                               SelectCategory (item.Category.Name);
+                                                       PreferencesKeys.HideInAllTaskList);
+                                       if (taskListsToHide != null && taskListsToHide.Contains 
(item.ITaskList.Name)) {
+                                               SelectTaskList (item.ITaskList.Name);
                                        }
-                               } else if (selectedCategory.Name.CompareTo (item.Category.Name) != 0) {
-                                       SelectCategory (item.Category.Name);
+                               } else if (selectedTaskList.Name.CompareTo (item.ITaskList.Name) != 0) {
+                                       SelectTaskList (item.ITaskList.Name);
                                }
                        }
                        
-                       ITask task = CreateTask (newTaskText, item.Category);
+                       ITask task = CreateTask (newTaskText, item.ITaskList);
                        
                        HighlightTask (task);
                }
                
-               void OnCategoryChanged (object sender, EventArgs args)
+               void OnTaskListChanged (object sender, EventArgs args)
                {
                        Gtk.TreeIter iter;
-                       if (!categoryComboBox.GetActiveIter (out iter))
+                       if (!taskListComboBox.GetActiveIter (out iter))
                                return;
                        
-                       ICategory category =
-                               categoryComboBox.Model.GetValue (iter, 0) as ICategory;
+                       ITaskList taskList =
+                               taskListComboBox.Model.GetValue (iter, 0) as ITaskList;
                                
                        // Update the TaskGroups so they can filter accordingly
-                       overdueGroup.Refilter (category);
-                       todayGroup.Refilter (category);
-                       tomorrowGroup.Refilter (category);
-                       nextSevenDaysGroup.Refilter (category);
-                       futureGroup.Refilter (category);
-                       completedTaskGroup.Refilter (category);
-                       
-                       // Save the selected category in preferences
-                       application.Preferences.Set (PreferencesKeys.SelectedCategoryKey,
-                                                                                category.Name);
+                       overdueGroup.Refilter (taskList);
+                       todayGroup.Refilter (taskList);
+                       tomorrowGroup.Refilter (taskList);
+                       nextSevenDaysGroup.Refilter (taskList);
+                       futureGroup.Refilter (taskList);
+                       completedTaskGroup.Refilter (taskList);
+                       
+                       // Save the selected taskList in preferences
+                       application.Preferences.Set (PreferencesKeys.SelectedTaskListKey,
+                                                                                taskList.Name);
                }
                
                void OnRowActivated (object sender, Gtk.RowActivatedArgs args)
@@ -1095,34 +1087,34 @@ namespace Gtk.Tasque
                                        popupMenu.Add (item);
 
                                        /*
-                                        * Depending on the currently selected task's category, we create a 
context popup
-                                        * 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.
+                                        * Depending on the currently selected task's taskList, we create a 
context popup
+                                        * here in order to enable changing taskLists. The list of available 
taskLists
+                                        * is pre-filtered as to not contain the current taskList and the 
AllTaskList.
                                         */
 
-                                   var filteredCategories = new ListStore (typeof (ICategory));
-                                   foreach (var cat in application.Backend.Categories) {
-                                           if (cat != null && !(cat is AllCategory) && !cat.Equals 
(clickedTask.Category))
-                                                   filteredCategories.AppendValues (cat);
+                                   var filteredTaskLists = new ListStore (typeof (ITaskList));
+                                   foreach (var cat in application.BackendManager.TaskLists) {
+                                           if (cat != null && !(cat is AllList) && !cat.Contains 
(clickedTask))
+                                                   filteredTaskLists.AppendValues (cat);
                                }
 
-                                       // The categories submenu is only created in case we actually provide 
at least one category.
-                                       if (filteredCategories.GetIterFirst(out iter))
+                                       // The taskLists submenu is only created in case we actually provide 
at least one taskList.
+                                       if (filteredTaskLists.GetIterFirst(out iter))
                                        {
-                                               Menu categoryMenu = new Menu();
-                                               CategoryMenuItem categoryItem;
+                                               Menu taskListMenu = new Menu();
+                                               TaskListMenuItem taskListItem;
 
-                                               filteredCategories.Foreach(delegate(TreeModel t, TreePath p, 
TreeIter i) {
-                                                       categoryItem = new 
CategoryMenuItem((ICategory)t.GetValue(i, 0));
-                                                       categoryItem.Activated += OnChangeCategory;
-                                                       categoryMenu.Add(categoryItem);
+                                               filteredTaskLists.Foreach(delegate(TreeModel t, TreePath p, 
TreeIter i) {
+                                                       taskListItem = new 
TaskListMenuItem((ITaskList)t.GetValue(i, 0));
+                                                       taskListItem.Activated += OnChangeTaskList;
+                                                       taskListMenu.Add(taskListItem);
                                                        return false;
                                                });
                                        
                                                // TODO Needs translation.
-                                               item = new ImageMenuItem(Catalog.GetString("_Change 
category"));
+                                               item = new ImageMenuItem(Catalog.GetString("_Change list"));
                                                item.Image = new Gtk.Image(Gtk.Stock.Convert, IconSize.Menu);
-                                               item.Submenu = categoryMenu;
+                                               item.Submenu = taskListMenu;
                                                popupMenu.Add(item);
                                        }
                                
@@ -1138,11 +1130,11 @@ namespace Gtk.Tasque
                {
                        if (args.Event.Button == 1) {
                                Gtk.TreeIter iter;
-                               if (!categoryComboBox.GetActiveIter (out iter))
+                               if (!taskListComboBox.GetActiveIter (out iter))
                                        return;
 
-                               ICategory category =
-                                       categoryComboBox.Model.GetValue (iter, 0) as ICategory;
+                               ITaskList taskList =
+                                       taskListComboBox.Model.GetValue (iter, 0) as ITaskList;
 
                                TaskView tree = futureGroup.TaskView as TaskView;
 
@@ -1150,7 +1142,7 @@ namespace Gtk.Tasque
                                if (tree.IsTaskBeingEdited)
                                        return;
 
-                               ITask task = CreateTask (String.Empty, category);
+                               ITask task = CreateTask (String.Empty, taskList);
                                if (task == null)
                                        return; // TODO: explain error to user
 
@@ -1174,9 +1166,11 @@ namespace Gtk.Tasque
                        if (clickedTask == null)
                                return;
                
-                       application.Backend.DeleteTask(clickedTask);
+                       var taskList = application.BackendManager.TaskLists.First (
+                               l => !(l is AllList) && l.Contains (clickedTask));
+                       taskList.Remove (clickedTask);
                        
-                       status = Catalog.GetString ("Task deleted");
+                       status = Catalog.GetString ("ITask deleted");
                        TaskWindow.ShowStatus (status);
                }
 
@@ -1198,50 +1192,32 @@ namespace Gtk.Tasque
                                return;
                        }
                        
-                       if (!noteDialogs.ContainsKey (dialog.Task)) {
+                       if (!noteDialogs.ContainsKey (dialog.ITask)) {
                                Logger.Warn ("Closed NoteDialog not found in noteDialogs");
                                return;
                        }
                        
                        Logger.Debug ("Removing NoteDialog from noteDialogs");
-                       noteDialogs.Remove (dialog.Task);
+                       noteDialogs.Remove (dialog.ITask);
                        
                        dialog.Destroy ();
                }
                
-               private void OnBackendInitialized()
-               {               
-                       backend.BackendInitialized -= OnBackendInitialized;
-                       PopulateWindow();
-                       OnBackendSyncFinished (); // To update the statusbar
-               }
-               
-               private void OnBackendSyncStarted ()
+               private void OnBackendInitialized (object sender, EventArgs e)
                {
-                       TaskWindow.ShowStatus (Catalog.GetString ("Loading tasks..."));
-               }
-               
-               private void OnBackendSyncFinished ()
-               {
-                       Logger.Debug("Backend sync finished");
-                       if (application.Backend.Configured) {
-                               string now = DateTime.Now.ToString ();
-                               // Translators: This status shows the date and time when the task list was 
last refreshed
-                               status = string.Format (Catalog.GetString ("Tasks loaded: {0}"), now);
-                               TaskWindow.lastLoadedTime = now;
-                               TaskWindow.ShowStatus (status);
-                               RebuildAddTaskMenu (application.Backend.Categories);
-                               addTaskEntry.Sensitive = true;
-                               categoryComboBox.Sensitive = true;
-                               // Keep insensitive text color
-                               Gdk.Color insensitiveColor =
-                                       addTaskEntry.Style.Text (Gtk.StateType.Insensitive);
-                               addTaskEntry.ModifyText (Gtk.StateType.Normal, insensitiveColor);
-                       } else {
-                               string status =
-                                       string.Format (Catalog.GetString ("Not connected."));
-                               TaskWindow.ShowStatus (status);
-                       }
+                       PopulateWindow();
+                       string now = DateTime.Now.ToString ();
+                       // Translators: This status shows the date and time when the task list was last 
refreshed
+                       status = string.Format (Catalog.GetString ("Tasks loaded: {0}"), now);
+                       TaskWindow.lastLoadedTime = now;
+                       TaskWindow.ShowStatus (status);
+                       RebuildAddTaskMenu (application.BackendManager.TaskLists);
+                       addTaskEntry.Sensitive = true;
+                       taskListComboBox.Sensitive = true;
+                       // Keep insensitive text color
+                       Gdk.Color insensitiveColor =
+                               addTaskEntry.Style.Text (Gtk.StateType.Insensitive);
+                       addTaskEntry.ModifyText (Gtk.StateType.Normal, insensitiveColor);
                }
 
                void KeyPressed (object sender, Gtk.KeyPressEventArgs args)
@@ -1256,26 +1232,33 @@ namespace Gtk.Tasque
                        args.RetVal = false;
                }
 
-               private void OnChangeCategory(object sender, EventArgs args)
+               private void OnChangeTaskList(object sender, EventArgs args)
                {
                        if (clickedTask == null)
                                return;
 
-                       clickedTask.Category = ((CategoryMenuItem)sender).Category;
+                       // NOTE: the previous data model had a one taskList to many tasks
+                       // relationship. Now it's many-to-many. However, we stick to the
+                       // old model until a general overhaul.
+                       var prevList = application.BackendManager.TaskLists.FirstOrDefault (
+                               c => !(c is AllList) && c.Contains (clickedTask));
+                       prevList.Remove (clickedTask);
+                       var list = ((TaskListMenuItem)sender).ITaskList;
+                       list.Add (clickedTask);
                }
                #endregion // Event Handlers
                
                #region Private Classes
-               class CategoryMenuItem : Gtk.MenuItem
+               class TaskListMenuItem : Gtk.MenuItem
                {
-                       private ICategory cat;
+                       private ITaskList cat;
                        
-                       public CategoryMenuItem (ICategory category) : base (category.Name)
+                       public TaskListMenuItem (ITaskList taskList) : base (taskList.Name)
                        {
-                               cat = category;
+                               cat = taskList;
                        }
                        
-                       public ICategory Category
+                       public ITaskList ITaskList
                        {
                                get { return cat; }
                        }
diff --git a/src/Gtk.Tasque/Tasque.exe.Defines.config b/src/Gtk.Tasque/Tasque.exe.Defines.config
new file mode 100644
index 0000000..33dc1f8
--- /dev/null
+++ b/src/Gtk.Tasque/Tasque.exe.Defines.config
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<configuration>
+  <appSettings>
+    <add key="DataDir" value="/home/antonius/Projects/tasque/build/bin/share" />
+  </appSettings>
+</configuration>
\ No newline at end of file
diff --git a/src/tasque/Tasque.exe.Defines.config.in b/src/Gtk.Tasque/Tasque.exe.Defines.config.in
similarity index 100%
rename from src/tasque/Tasque.exe.Defines.config.in
rename to src/Gtk.Tasque/Tasque.exe.Defines.config.in
diff --git a/src/tasque/Tasque.exe.config b/src/Gtk.Tasque/Tasque.exe.config
similarity index 100%
rename from src/tasque/Tasque.exe.config
rename to src/Gtk.Tasque/Tasque.exe.config
diff --git a/src/Gtk.Tasque/Utilities.cs b/src/Gtk.Tasque/Utilities.cs
index ac5135e..cb9f344 100644
--- a/src/Gtk.Tasque/Utilities.cs
+++ b/src/Gtk.Tasque/Utilities.cs
@@ -40,8 +40,9 @@ using System.Security.Cryptography;
 using Mono.Unix;
 using Gdk;
 using Gtk;
+using Tasque;
 
-namespace Tasque
+namespace Gtk.Tasque
 {
        // TODO: Change this class to internal
        public static partial class Utilities
diff --git a/src/tasque/tasque.in b/src/Gtk.Tasque/tasque.in
similarity index 100%
rename from src/tasque/tasque.in
rename to src/Gtk.Tasque/tasque.in
diff --git a/src/tasque/tasque.pc.in b/src/Gtk.Tasque/tasque.pc.in
similarity index 100%
rename from src/tasque/tasque.pc.in
rename to src/Gtk.Tasque/tasque.pc.in
diff --git a/src/Libraries/RtmNet/RtmNet.csproj b/src/Libraries/RtmNet/RtmNet.csproj
index 1276928..3b57c24 100644
--- a/src/Libraries/RtmNet/RtmNet.csproj
+++ b/src/Libraries/RtmNet/RtmNet.csproj
@@ -12,7 +12,7 @@
     <RootNamespace>RtmNet</RootNamespace>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
-    <ReleaseVersion>0.1.13</ReleaseVersion>
+    <ReleaseVersion>0.2.0</ReleaseVersion>
     <BuildEnabled>$(EnableBackendRtm)</BuildEnabled>
     <PackageName>tasque</PackageName>
     <TopBuildDir>..\..\..</TopBuildDir>
diff --git a/src/MonoMac.Tasque/MonoMac.Tasque.csproj b/src/MonoMac.Tasque/MonoMac.Tasque.csproj
index b526dea..13ab4e1 100644
--- a/src/MonoMac.Tasque/MonoMac.Tasque.csproj
+++ b/src/MonoMac.Tasque/MonoMac.Tasque.csproj
@@ -9,7 +9,7 @@
     <OutputType>Library</OutputType>
     <RootNamespace>MonoMac.Tasque</RootNamespace>
     <AssemblyName>MonoMac.Tasque</AssemblyName>
-    <ReleaseVersion>0.1.13</ReleaseVersion>
+    <ReleaseVersion>0.2.0</ReleaseVersion>
     <PackageName>tasque</PackageName>
     <TopBuildDir>..\..</TopBuildDir>
   </PropertyGroup>
diff --git a/src/libtasque/Core/BackendManager.cs b/src/libtasque/Core/BackendManager.cs
new file mode 100644
index 0000000..5ed058b
--- /dev/null
+++ b/src/libtasque/Core/BackendManager.cs
@@ -0,0 +1,216 @@
+//
+// BackendManager.cs
+//
+// Author:
+//       Antonius Riha <antoniusriha gmail com>
+//
+// Copyright (c) 2013 Antonius Riha
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using Tasque.Core.Impl;
+using Tasque.Data;
+
+namespace Tasque.Core
+{
+       public class BackendManager : IDisposable
+       {
+               /// <summary>
+               /// Initializes a new instance of the
+               /// <see cref="Tasque.Core.BackendManager"/> class.
+               /// </summary>
+               /// <param name='preferences'>
+               /// Preferences.
+               /// </param>
+               /// <exception cref="T:System.ArgumentNullException">
+               /// thrown when preferences is <c>null</c>.
+               /// </exception>
+               public BackendManager (IPreferences preferences)
+               {
+                       manager = new InternalBackendManager (preferences);
+                       
+                       // setup backend manager for AllList
+                       Tasque.Utils.AllList.SetBackendManager (this);
+               }
+               
+               /// <summary>
+               /// Gets the available backend ids and the corresponding
+               /// human-readable names.
+               /// </summary>
+               /// <value>
+               /// The available backends.
+               /// </value>
+               /// <exception cref="T:System.ObjectDisposedException">
+               /// thrown when the object has been disposed.
+               /// </exception>
+               public IDictionary<string, string> AvailableBackends {
+                       get { return manager.AvailableBackends; }
+               }
+
+               /// <summary>
+               /// Gets the id of the current backend.
+               /// </summary>
+               /// <value>
+               /// The id of the current backend.
+               /// </value>
+               /// <exception cref="T:System.ObjectDisposedException">
+               /// thrown when the object has been disposed.
+               /// </exception>
+               public string CurrentBackend { get { return manager.CurrentBackend; } }
+
+               /// <summary>
+               /// Gets a value indicating whether the current backend is initialized.
+               /// </summary>
+               /// <value>
+               /// <c>true</c> if backend is initialized; otherwise, <c>false</c>.
+               /// </value>
+               public bool IsBackendInitialized {
+                       get { return manager.IsBackendInitialized; }
+               }
+               
+               /// <summary>
+               /// Gets a value indicating whether the current backend is configured.
+               /// </summary>
+               /// <value>
+               /// <c>true</c> if the backend is configured; otherwise, <c>false</c>.
+               /// </value>
+               public bool IsBackendConfigured {
+                       get { return manager.IsBackendConfigured; }
+               }
+               
+               /// <summary>
+               /// Gets the task lists.
+               /// </summary>
+               /// <value>
+               /// The task lists.
+               /// </value>
+               /// <exception cref="T:System.ObjectDisposedException">
+               /// thrown when the object has been disposed.
+               /// </exception>
+               public ObservableCollection<ITaskList> TaskLists {
+                       get { return manager.TaskLists; }
+               }
+
+               /// <summary>
+               /// Gets all tasks of the current backend.
+               /// </summary>
+               /// <value>
+               /// The tasks.
+               /// </value>
+               /// <exception cref="T:System.ObjectDisposedException">
+               /// thrown when the object has been disposed.
+               /// </exception>
+               public ReadOnlyObservableCollection<ITask> Tasks {
+                       get { return manager.Tasks; }
+               }
+
+               /// <summary>
+               /// Sets the backend.
+               /// </summary>
+               /// <param name='backendType'>
+               /// The backend id. This must be one of <see cref="AvailableBackends"/>
+               /// 's ids or <c>null</c>.
+               /// </param>
+               /// <exception cref="T:System.ObjectDisposedException">
+               /// thrown when the object has been disposed.
+               /// </exception>
+               /// <exception cref="T:System.ArgumentException">
+               /// thrown when the provided backendType is not one of AvailableBackends.
+               /// </exception>
+               public void SetBackend (string id)
+               {
+                       manager.SetBackend (id);
+               }
+
+               /// <summary>
+               /// Reinitializes the current backend. This is a no-op, if
+               /// <see cref="CurrentBackendType"/> is <c>null</c>.
+               /// </summary>
+               /// <exception cref="T:System.ObjectDisposedException">
+               /// thrown when the object has been disposed.
+               /// </exception>
+               public void ReInitializeBackend ()
+               {
+                       manager.ReInitializeBackend ();
+               }
+
+               /// <summary>
+               /// Gets the backend preferences widget.
+               /// </summary>
+               /// <returns>
+               /// The backend preferences widget.
+               /// </returns>
+               public IBackendPreferences GetBackendPreferencesWidget ()
+               {
+                       return manager.GetBackendPreferencesWidget ();
+               }
+
+               /// <summary>
+               /// Releases all resource used by the <see cref="Tasque.Core.BackendManager"/> object.
+               /// </summary>
+               /// <remarks>
+               /// Call <see cref="Dispose"/> when you are finished using the <see 
cref="Tasque.Core.BackendManager"/>. The
+               /// <see cref="Dispose"/> method leaves the <see cref="Tasque.Core.BackendManager"/> in an 
unusable state. After
+               /// calling <see cref="Dispose"/>, you must release all references to the <see 
cref="Tasque.Core.BackendManager"/> so
+               /// the garbage collector can reclaim the memory that the <see 
cref="Tasque.Core.BackendManager"/> was occupying.
+               /// </remarks>
+               public void Dispose ()
+               {
+                       manager.Dispose ();
+               }
+
+               /// <summary>
+               /// Occurs when the backend has been changed. This doesn't necessarily
+               /// imply that the new backend has been initialized and is ready for
+               /// use. Use <see cref="BackendInitialized"/> for that.
+               /// </summary>
+               public event EventHandler BackendChanged {
+                       add { manager.BackendChanged += value; }
+                       remove { manager.BackendChanged -= value; }
+               }
+
+               /// <summary>
+               /// Occurs when the backend is changing.
+               /// </summary>
+               public event EventHandler BackendChanging {
+                       add { manager.BackendChanging += value; }
+                       remove { manager.BackendChanging -= value; }
+               }
+
+               /// <summary>
+               /// Occurs when th backend has been initialized and is ready to use.
+               /// </summary>
+               public event EventHandler BackendInitialized {
+                       add { manager.BackendInitialized += value; }
+                       remove { manager.BackendInitialized -= value; }
+               }
+
+               /// <summary>
+               /// Occurs when the current backend needs configuration.
+               /// </summary>
+               public event EventHandler BackendConfigurationRequested {
+                       add { manager.BackendConfigurationRequested += value; }
+                       remove { manager.BackendConfigurationRequested -= value; }
+               }
+               
+               InternalBackendManager manager;
+       }
+}
diff --git a/src/libtasque/IBackendPreferences.cs b/src/libtasque/Core/INote.cs
similarity index 87%
copy from src/libtasque/IBackendPreferences.cs
copy to src/libtasque/Core/INote.cs
index 1f1a236..e3818de 100644
--- a/src/libtasque/IBackendPreferences.cs
+++ b/src/libtasque/Core/INote.cs
@@ -1,21 +1,21 @@
-// 
-// IBackendPreferences.cs
-//  
+//
+// INote.cs
+//
 // Author:
 //       Antonius Riha <antoniusriha gmail com>
-// 
-// Copyright (c) 2012 Antonius Riha
-// 
+//
+// Copyright (c) 2013 Antonius Riha
+//
 // Permission is hereby granted, free of charge, to any person obtaining a copy
 // of this software and associated documentation files (the "Software"), to deal
 // in the Software without restriction, including without limitation the rights
 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 // copies of the Software, and to permit persons to whom the Software is
 // furnished to do so, subject to the following conditions:
-// 
+//
 // The above copyright notice and this permission notice shall be included in
 // all copies or substantial portions of the Software.
-// 
+//
 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -23,10 +23,7 @@
 // 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.Backends
+namespace Tasque.Core
 {
-       public interface IBackendPreferences
-       {
-       }
+       public interface INote : INoteCore, ITasqueObject {}
 }
diff --git a/src/libtasque/TaskComparer.cs b/src/libtasque/Core/ITask.cs
similarity index 56%
copy from src/libtasque/TaskComparer.cs
copy to src/libtasque/Core/ITask.cs
index 1285fe1..e2e9399 100644
--- a/src/libtasque/TaskComparer.cs
+++ b/src/libtasque/Core/ITask.cs
@@ -1,10 +1,10 @@
 //
-// TaskComparer.cs
+// ITask.cs
 //
 // Author:
 //       Antonius Riha <antoniusriha gmail com>
 //
-// Copyright (c) 2012 Antonius Riha
+// Copyright (c) 2013 Antonius Riha
 //
 // Permission is hereby granted, free of charge, to any person obtaining a copy
 // of this software and associated documentation files (the "Software"), to deal
@@ -23,18 +23,40 @@
 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 // THE SOFTWARE.
+using System;
 using System.Collections.Generic;
+using System.Collections.ObjectModel;
 
-namespace Tasque
+namespace Tasque.Core
 {
-       public class TaskComparer : Comparer<ITask>
+       public interface ITask : ITaskCore, ITasqueObject
        {
-               public override int Compare (ITask x, ITask y)
-               {
-                       if (x == null || y == null)
-                               return 0;
-                       
-                       return (x.CompareTo (y));
-               }
+               DateTime CompletionDate { get; }
+               bool IsComplete { get; }
+               TaskState State { get; }
+
+               NoteSupport NoteSupport { get; }
+               bool SupportsSharingNotesWithOtherTasks { get; }
+               bool HasNotes { get; }
+               ObservableCollection<INote> Notes { get; }
+               INote Note { get; set; }
+
+               bool SupportsNestedTasks { get; }
+               bool SupportsSharingNestedTasksWithOtherTasks { get; }
+               bool HasNestedTasks { get; }
+               ObservableCollection<ITask> NestedTasks { get; }
+
+               bool SupportsDiscarding { get; }
+
+               void Activate ();
+               void Complete ();
+               void Discard ();
+
+               INote CreateNote ();
+               INote CreateNote (string text);
+               ITask CreateNestedTask (string text);
+
+               event EventHandler Completing, Completed,
+                       Activating, Activated, Discarding, Discarded;
        }
 }
diff --git a/src/libtasque/CategoryComparer.cs b/src/libtasque/Core/ITaskList.cs
similarity index 76%
copy from src/libtasque/CategoryComparer.cs
copy to src/libtasque/Core/ITaskList.cs
index b81fcfa..668aeba 100644
--- a/src/libtasque/CategoryComparer.cs
+++ b/src/libtasque/Core/ITaskList.cs
@@ -1,10 +1,10 @@
 //
-// CategoryComparer.cs
+// ITaskList.cs
 //
 // Author:
 //       Antonius Riha <antoniusriha gmail com>
 //
-// Copyright (c) 2012 Antonius Riha
+// Copyright (c) 2013 Antonius Riha
 //
 // Permission is hereby granted, free of charge, to any person obtaining a copy
 // of this software and associated documentation files (the "Software"), to deal
@@ -24,22 +24,18 @@
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 // THE SOFTWARE.
 using System.Collections.Generic;
+using System.Collections.Specialized;
 
-namespace Tasque
+namespace Tasque.Core
 {
-       public class CategoryComparer : Comparer<ICategory>
+       public interface ITaskList : ITaskListCore, ITasqueObject,
+               ICollection<ITask>, INotifyCollectionChanged
        {
-               public override int Compare (ICategory x, ICategory y)
-               {
-                       if (x == null || y == null)
-                               return 0;
-                       
-                       if (x is AllCategory)
-                               return -1;
-                       else if (y is AllCategory)
-                               return 1;
-                       
-                       return (x.Name.CompareTo (y.Name));
-               }
+               bool SupportsSharingTasksWithOtherTaskLists { get; }
+               bool CanChangeName { get; }
+
+               TaskListType ListType { get; }
+
+               ITask CreateTask (string text);
        }
 }
diff --git a/src/libtasque/IBackendPreferences.cs b/src/libtasque/Core/ITasqueObject.cs
similarity index 82%
copy from src/libtasque/IBackendPreferences.cs
copy to src/libtasque/Core/ITasqueObject.cs
index 1f1a236..86fe130 100644
--- a/src/libtasque/IBackendPreferences.cs
+++ b/src/libtasque/Core/ITasqueObject.cs
@@ -1,21 +1,21 @@
-// 
-// IBackendPreferences.cs
-//  
+//
+// ITasqueObject.cs
+//
 // Author:
 //       Antonius Riha <antoniusriha gmail com>
-// 
-// Copyright (c) 2012 Antonius Riha
-// 
+//
+// Copyright (c) 2013 Antonius Riha
+//
 // Permission is hereby granted, free of charge, to any person obtaining a copy
 // of this software and associated documentation files (the "Software"), to deal
 // in the Software without restriction, including without limitation the rights
 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 // copies of the Software, and to permit persons to whom the Software is
 // furnished to do so, subject to the following conditions:
-// 
+//
 // The above copyright notice and this permission notice shall be included in
 // all copies or substantial portions of the Software.
-// 
+//
 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -23,10 +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.ComponentModel;
 
-namespace Tasque.Backends
+namespace Tasque.Core
 {
-       public interface IBackendPreferences
+       public interface ITasqueObject
+               : ITasqueCore, INotifyPropertyChanged, INotifyPropertyChanging
        {
+               void Refresh ();
        }
 }
diff --git a/src/libtasque/CategoryComparer.cs b/src/libtasque/Core/Impl/Extensions.cs
similarity index 63%
copy from src/libtasque/CategoryComparer.cs
copy to src/libtasque/Core/Impl/Extensions.cs
index b81fcfa..fbf8dad 100644
--- a/src/libtasque/CategoryComparer.cs
+++ b/src/libtasque/Core/Impl/Extensions.cs
@@ -1,10 +1,10 @@
 //
-// CategoryComparer.cs
+// Extensions.cs
 //
 // Author:
 //       Antonius Riha <antoniusriha gmail com>
 //
-// Copyright (c) 2012 Antonius Riha
+// Copyright (c) 2013 Antonius Riha
 //
 // Permission is hereby granted, free of charge, to any person obtaining a copy
 // of this software and associated documentation files (the "Software"), to deal
@@ -23,23 +23,31 @@
 // 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.Generic;
+using System;
 
-namespace Tasque
+namespace Tasque.Core.Impl
 {
-       public class CategoryComparer : Comparer<ICategory>
+       public static class Extensions
        {
-               public override int Compare (ICategory x, ICategory y)
+               public static void SetProperty<TProperty, T> (
+                       this T source, string name, TProperty val, TProperty curVal,
+                       Action<TProperty> setVal, Func<T, TProperty, TProperty> update)
+                       where T : ITasqueObject, IBackendDetachable, INotifying
                {
-                       if (x == null || y == null)
-                               return 0;
+                       if (source == null)
+                               throw new NullReferenceException ("source");
                        
-                       if (x is AllCategory)
-                               return -1;
-                       else if (y is AllCategory)
-                               return 1;
+                       if (Equals (val, curVal))
+                               return;
                        
-                       return (x.Name.CompareTo (y.Name));
+                       if (!source.IsBackendDetached) {
+                               if (Equals (curVal, val = update (source, val)))
+                                       return;
+                       }
+                       
+                       source.OnPropertyChanging (name);
+                       setVal (val);
+                       source.OnPropertyChanged (name);
                }
        }
 }
diff --git a/src/libtasque/IBackendPreferences.cs b/src/libtasque/Core/Impl/IBackendDetachable.cs
similarity index 80%
copy from src/libtasque/IBackendPreferences.cs
copy to src/libtasque/Core/Impl/IBackendDetachable.cs
index 1f1a236..39b7b0a 100644
--- a/src/libtasque/IBackendPreferences.cs
+++ b/src/libtasque/Core/Impl/IBackendDetachable.cs
@@ -1,21 +1,21 @@
-// 
-// IBackendPreferences.cs
-//  
+//
+// IBackendDetachable.cs
+//
 // Author:
 //       Antonius Riha <antoniusriha gmail com>
-// 
-// Copyright (c) 2012 Antonius Riha
-// 
+//
+// Copyright (c) 2013 Antonius Riha
+//
 // Permission is hereby granted, free of charge, to any person obtaining a copy
 // of this software and associated documentation files (the "Software"), to deal
 // in the Software without restriction, including without limitation the rights
 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 // copies of the Software, and to permit persons to whom the Software is
 // furnished to do so, subject to the following conditions:
-// 
+//
 // The above copyright notice and this permission notice shall be included in
 // all copies or substantial portions of the Software.
-// 
+//
 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -23,10 +23,12 @@
 // 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.Backends
+namespace Tasque.Core.Impl
 {
-       public interface IBackendPreferences
+       public interface IBackendDetachable
        {
+               bool IsBackendDetached { get; }
+               void DetachBackend (ITasqueObject container);
+               void AttachBackend (ITasqueObject container);
        }
 }
diff --git a/src/tasque/Properties/AssemblyInfo.cs b/src/libtasque/Core/Impl/IContainer.cs
similarity index 83%
rename from src/tasque/Properties/AssemblyInfo.cs
rename to src/libtasque/Core/Impl/IContainer.cs
index e224beb..26d5f6e 100644
--- a/src/tasque/Properties/AssemblyInfo.cs
+++ b/src/libtasque/Core/Impl/IContainer.cs
@@ -1,21 +1,21 @@
-// 
-// AssemblyInfo.cs
-//  
+//
+// IContainer.cs
+//
 // Author:
 //       Antonius Riha <antoniusriha gmail com>
-// 
-// Copyright (c) 2012 Antonius Riha
-// 
+//
+// Copyright (c) 2013 Antonius Riha
+//
 // Permission is hereby granted, free of charge, to any person obtaining a copy
 // of this software and associated documentation files (the "Software"), to deal
 // in the Software without restriction, including without limitation the rights
 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 // copies of the Software, and to permit persons to whom the Software is
 // furnished to do so, subject to the following conditions:
-// 
+//
 // The above copyright notice and this permission notice shall be included in
 // all copies or substantial portions of the Software.
-// 
+//
 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -23,7 +23,12 @@
 // 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.Reflection;
+using System.Collections.Generic;
 
-[assembly: AssemblyTitle("Tasque")]
-[assembly: AssemblyDescription("Tasque application. Simple Tasque Management.")]
+namespace Tasque.Core.Impl
+{
+       public interface IContainer<out T>
+       {
+               IEnumerable<T> Items { get; }
+       }
+}
diff --git a/src/libtasque/IBackendPreferences.cs b/src/libtasque/Core/Impl/IIdEditable.cs
similarity index 86%
copy from src/libtasque/IBackendPreferences.cs
copy to src/libtasque/Core/Impl/IIdEditable.cs
index 1f1a236..48ce370 100644
--- a/src/libtasque/IBackendPreferences.cs
+++ b/src/libtasque/Core/Impl/IIdEditable.cs
@@ -1,21 +1,21 @@
-// 
-// IBackendPreferences.cs
-//  
+//
+// IIdEditable.cs
+//
 // Author:
 //       Antonius Riha <antoniusriha gmail com>
-// 
-// Copyright (c) 2012 Antonius Riha
-// 
+//
+// Copyright (c) 2013 Antonius Riha
+//
 // Permission is hereby granted, free of charge, to any person obtaining a copy
 // of this software and associated documentation files (the "Software"), to deal
 // in the Software without restriction, including without limitation the rights
 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 // copies of the Software, and to permit persons to whom the Software is
 // furnished to do so, subject to the following conditions:
-// 
+//
 // The above copyright notice and this permission notice shall be included in
 // all copies or substantial portions of the Software.
-// 
+//
 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -23,10 +23,10 @@
 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 // THE SOFTWARE.
-
-namespace Tasque.Backends
+namespace Tasque.Core.Impl
 {
-       public interface IBackendPreferences
+       public interface IIdEditable<out T> where T : ITasqueCore
        {
+               void SetId (string id);
        }
 }
diff --git a/src/libtasque/TaskComparer.cs b/src/libtasque/Core/Impl/IInternalContainee.cs
similarity index 78%
copy from src/libtasque/TaskComparer.cs
copy to src/libtasque/Core/Impl/IInternalContainee.cs
index 1285fe1..6a679c5 100644
--- a/src/libtasque/TaskComparer.cs
+++ b/src/libtasque/Core/Impl/IInternalContainee.cs
@@ -1,10 +1,10 @@
 //
-// TaskComparer.cs
+// IInternalContainee.cs
 //
 // Author:
 //       Antonius Riha <antoniusriha gmail com>
 //
-// Copyright (c) 2012 Antonius Riha
+// Copyright (c) 2013 Antonius Riha
 //
 // Permission is hereby granted, free of charge, to any person obtaining a copy
 // of this software and associated documentation files (the "Software"), to deal
@@ -23,18 +23,14 @@
 // 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.Generic;
+using System.Collections.ObjectModel;
 
-namespace Tasque
+namespace Tasque.Core.Impl
 {
-       public class TaskComparer : Comparer<ITask>
+       public interface IInternalContainee<TContainer, out T>
+               : IContainee<TContainer>
+               where TContainer : ITasqueObject, IContainer<T>
        {
-               public override int Compare (ITask x, ITask y)
-               {
-                       if (x == null || y == null)
-                               return 0;
-                       
-                       return (x.CompareTo (y));
-               }
+               Collection<TContainer> InternalContainers { get; }
        }
 }
diff --git a/src/libtasque/IBackendPreferences.cs b/src/libtasque/Core/Impl/IInternalTasqueObject.cs
similarity index 85%
copy from src/libtasque/IBackendPreferences.cs
copy to src/libtasque/Core/Impl/IInternalTasqueObject.cs
index 1f1a236..8202835 100644
--- a/src/libtasque/IBackendPreferences.cs
+++ b/src/libtasque/Core/Impl/IInternalTasqueObject.cs
@@ -1,21 +1,21 @@
-// 
-// IBackendPreferences.cs
-//  
+//
+// IInternalTasqueObject.cs
+//
 // Author:
 //       Antonius Riha <antoniusriha gmail com>
-// 
-// Copyright (c) 2012 Antonius Riha
-// 
+//
+// Copyright (c) 2013 Antonius Riha
+//
 // Permission is hereby granted, free of charge, to any person obtaining a copy
 // of this software and associated documentation files (the "Software"), to deal
 // in the Software without restriction, including without limitation the rights
 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 // copies of the Software, and to permit persons to whom the Software is
 // furnished to do so, subject to the following conditions:
-// 
+//
 // The above copyright notice and this permission notice shall be included in
 // all copies or substantial portions of the Software.
-// 
+//
 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -23,10 +23,10 @@
 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 // THE SOFTWARE.
-
-namespace Tasque.Backends
+namespace Tasque.Core.Impl
 {
-       public interface IBackendPreferences
+       public interface IInternalTasqueObject : ITasqueObject
        {
+               void Merge (ITasqueCore source);
        }
 }
diff --git a/src/libtasque/TaskComparer.cs b/src/libtasque/Core/Impl/INotifying.cs
similarity index 80%
copy from src/libtasque/TaskComparer.cs
copy to src/libtasque/Core/Impl/INotifying.cs
index 1285fe1..8dddcf8 100644
--- a/src/libtasque/TaskComparer.cs
+++ b/src/libtasque/Core/Impl/INotifying.cs
@@ -1,10 +1,10 @@
 //
-// TaskComparer.cs
+// INotifying.cs
 //
 // Author:
 //       Antonius Riha <antoniusriha gmail com>
 //
-// Copyright (c) 2012 Antonius Riha
+// Copyright (c) 2013 Antonius Riha
 //
 // Permission is hereby granted, free of charge, to any person obtaining a copy
 // of this software and associated documentation files (the "Software"), to deal
@@ -23,18 +23,14 @@
 // 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.Generic;
+using System.ComponentModel;
 
-namespace Tasque
+namespace Tasque.Core.Impl
 {
-       public class TaskComparer : Comparer<ITask>
+       public interface INotifying
+               : INotifyPropertyChanged, INotifyPropertyChanging
        {
-               public override int Compare (ITask x, ITask y)
-               {
-                       if (x == null || y == null)
-                               return 0;
-                       
-                       return (x.CompareTo (y));
-               }
+               void OnPropertyChanged (string propertyName);
+               void OnPropertyChanging (string propertyName);
        }
 }
diff --git a/src/libtasque/Core/Impl/InternalBackendManager.TaskListCollection.cs 
b/src/libtasque/Core/Impl/InternalBackendManager.TaskListCollection.cs
new file mode 100644
index 0000000..1bb0383
--- /dev/null
+++ b/src/libtasque/Core/Impl/InternalBackendManager.TaskListCollection.cs
@@ -0,0 +1,204 @@
+//
+// InternalBackendManager.TaskListCollection.cs
+//
+// Author:
+//       Antonius Riha <antoniusriha gmail com>
+//
+// Copyright (c) 2013 Antonius Riha
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using System.Collections.ObjectModel;
+using System.Collections.Specialized;
+using System.Linq;
+using Tasque.Data;
+
+namespace Tasque.Core.Impl
+{
+       public partial class InternalBackendManager
+       {
+               public class TaskListCollection : ObservableCollection<ITaskList>
+               {
+                       const string ItemExistsExMsg = "The specified TaskList exists already.";
+
+                       public TaskListCollection ()
+                       {
+                               tasks = new ObservableCollection<ITask> ();
+                               Tasks = new ReadOnlyObservableCollection<ITask> (tasks);
+                       }
+
+                       public bool IsLoaded { get; private set; }
+
+                       public ReadOnlyObservableCollection<ITask> Tasks { get; private set; }
+
+                       public void LoadTaskLists (IBackend2 backend)
+                       {
+                               if (backend == null)
+                                       throw new ArgumentNullException ("backend");
+                               this.backend = backend;
+
+                               if (IsLoaded)
+                                       UnloadTaskLists ();
+                               IsLoaded = true;
+
+                               var i = 0;
+                               foreach (var item in backend.GetAll ())
+                                       AddList (i++, (ITaskList)item, true);
+
+                               // enable backend propagation on all objects
+                               foreach (var list in this) {
+                                       if (list.ListType == TaskListType.Regular)
+                                               ((IBackendDetachable)list).AttachBackend (null);
+                               }
+                       }
+
+                       public void UnloadTaskLists ()
+                       {
+                               if (!IsLoaded)
+                                       return;
+                               IsLoaded = false;
+
+                               // disable backend propagation on all objects
+                               foreach (var list in this) {
+                                       if (list.ListType == TaskListType.Regular)
+                                               ((IBackendDetachable)list).DetachBackend (null);
+                               }
+
+                               foreach (var item in this)
+                                       RemoveList (0, item, true);
+                       }
+                       
+                       protected override void ClearItems ()
+                       {
+                               ThrowIfNotLoaded ();
+
+                               foreach (var item in this) {
+                                       backend.Delete (item);
+                                       item.CollectionChanged -= HandleTaskListChanged;
+                               }
+                               tasks.Clear ();
+                               base.ClearItems ();
+                       }
+                       
+                       protected override void InsertItem (int index, ITaskList item)
+                       {
+                               ThrowIfNotLoaded ();
+                               AddList (index, item, false);
+                       }
+                       
+                       protected override void RemoveItem (int index)
+                       {
+                               ThrowIfNotLoaded ();
+                               var oldList = this [index];
+                               RemoveList (index, oldList, false);
+                       }
+                       
+                       protected override void SetItem (int index, ITaskList item)
+                       {
+                               ThrowIfNotLoaded ();
+                               if (Contains (item))
+                                       throw new ArgumentException (ItemExistsExMsg, "item");
+
+                               var oldList = this [index];
+                               backend.Delete (oldList);
+                               item.CollectionChanged -= HandleTaskListChanged;
+                               foreach (var task in item)
+                                       RemoveTask (task);
+
+                               backend.Create (item);
+                               foreach (var task in item)
+                                       AddTask (task);
+                               item.CollectionChanged += HandleTaskListChanged;
+
+                               base.SetItem (index, item);
+                       }
+
+                       void AddList (int index, ITaskList item, bool isLoading)
+                       {
+                               if (Contains (item))
+                                       throw new ArgumentException (ItemExistsExMsg, "item");
+
+                               if (!isLoading) {
+                                       backend.Create (item);
+                                       ((IBackendDetachable)item).AttachBackend (null);
+                               }
+
+                               foreach (var task in item)
+                                       AddTask (task);
+                               item.CollectionChanged += HandleTaskListChanged;
+                               base.InsertItem (index, item);
+                       }
+
+                       void RemoveList (int index, ITaskList item, bool isUnloading)
+                       {
+                               if (!isUnloading) {
+                                       ((IBackendDetachable)item).DetachBackend (null);
+                                       backend.Delete (item);
+                               }
+
+                               item.CollectionChanged -= HandleTaskListChanged;
+                               foreach (var task in item)
+                                       RemoveTask (task);
+                               base.RemoveItem (index);
+                       }
+
+                       void HandleTaskListChanged (object sender, NotifyCollectionChangedEventArgs e)
+                       {
+                               switch (e.Action) {
+                               case NotifyCollectionChangedAction.Add:
+                                       AddTask (e.NewItems [0] as ITask);
+                                       break;
+                               case NotifyCollectionChangedAction.Remove:
+                                       RemoveTask (e.OldItems [0] as ITask);
+                                       break;
+                               case NotifyCollectionChangedAction.Replace:
+                                       RemoveTask (e.OldItems [0] as ITask);
+                                       AddTask (e.NewItems [0] as ITask);
+                                       break;
+                               case NotifyCollectionChangedAction.Reset:
+                                       foreach (var task in sender as ITaskList)
+                                               RemoveTask (task);
+                                       break;
+                               }
+                       }
+
+                       void AddTask (ITask task)
+                       {
+                               if (!tasks.Contains (task))
+                                       tasks.Add (task);
+                       }
+
+                       void RemoveTask (ITask task)
+                       {
+                               if (this.Count (l => l.Contains (task)) == 1)
+                                       tasks.Remove (task);
+                       }
+
+                       void ThrowIfNotLoaded ()
+                       {
+                               if (!IsLoaded)
+                                       throw new InvalidOperationException ("This method can" +
+                                               "only be called, when IsLoaded is true.");
+                       }
+                       
+                       ObservableCollection<ITask> tasks;
+                       IBackend2 backend;
+               }
+       }
+}
diff --git a/src/libtasque/Core/Impl/InternalBackendManager.cs 
b/src/libtasque/Core/Impl/InternalBackendManager.cs
new file mode 100644
index 0000000..52edb19
--- /dev/null
+++ b/src/libtasque/Core/Impl/InternalBackendManager.cs
@@ -0,0 +1,203 @@
+//
+// InternalBackendManager.cs
+//
+// Author:
+//       Antonius Riha <antoniusriha gmail com>
+//
+// Copyright (c) 2013 Antonius Riha
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using Mono.Addins;
+using Tasque.Data;
+
+namespace Tasque.Core.Impl
+{
+       using BackendNode = TypeExtensionNode<BackendExtensionAttribute>;
+
+       public partial class InternalBackendManager
+       {
+               public InternalBackendManager (IPreferences preferences)
+               {
+                       if (preferences == null)
+                               throw new ArgumentNullException ("preferences");
+                       this.preferences = preferences;
+                       
+                       availableBackendNodes = AddinManager
+                               .GetExtensionNodes<BackendNode> (typeof(IBackend2));
+
+                       taskLists = new TaskListCollection ();
+               }
+
+               public IDictionary<string, string> AvailableBackends {
+                       get {
+                               ThrowIfDisposed ();
+                               return availableBackendNodes.ToDictionary (
+                                       n => n.Id, n => n.Data.Name);
+                       }
+               }
+
+               public string CurrentBackend {
+                       get {
+                               ThrowIfDisposed ();
+                               return currentBackend;
+                       }
+               }
+               
+               public bool IsBackendInitialized {
+                       get {
+                               ThrowIfDisposed ();
+                               return backend != null ? backend.IsInitialized : false;
+                       }
+               }
+               
+               public bool IsBackendConfigured {
+                       get {
+                               ThrowIfDisposed ();
+                               return backend != null ? backend.IsConfigured : false;
+                       }
+               }
+
+               public ObservableCollection<ITaskList> TaskLists {
+                       get {
+                               ThrowIfDisposed ();
+                               return taskLists;
+                       }
+               }
+
+               public ReadOnlyObservableCollection<ITask> Tasks {
+                       get {
+                               ThrowIfDisposed ();
+                               return taskLists.Tasks;
+                       }
+               }
+
+               public void SetBackend (string id)
+               {
+                       ThrowIfDisposed ();
+                       if (id != null && !AvailableBackends.ContainsKey (id))
+                               throw new ArgumentException ("The provided backend type is" +
+                                       " not listed in AvailableBackends.", "id");
+
+                       if (currentBackend == id)
+                               return;
+
+                       if (BackendChanging != null)
+                               BackendChanging (this, EventArgs.Empty);
+
+                       currentBackend = id;
+                       ReInitializeBackend ();
+
+                       if (BackendChanged != null)
+                               BackendChanged (this, EventArgs.Empty);
+               }
+
+               public void ReInitializeBackend ()
+               {
+                       ThrowIfDisposed ();
+                       if (currentBackend == null)
+                               return;
+
+                       if (backend != null) {
+                               Logger.Debug ("Cleaning up backend: {0}", backend.GetType ());
+                               backend.Disposed += delegate {
+                                       backend = null;
+                                       InitializeBackend ();
+                               };
+                               backend.Dispose ();
+                               taskLists.UnloadTaskLists ();
+                       } else
+                               InitializeBackend ();
+               }
+               
+               public IBackendPreferences GetBackendPreferencesWidget ()
+               {
+                       ThrowIfDisposed ();
+                       return backend.Preferences;
+               }
+
+               public void Dispose ()
+               {
+                       Dispose (true);
+                       GC.SuppressFinalize (this);
+               }
+
+               protected virtual void Dispose (bool disposing)
+               {
+                       if (disposed)
+                               return;
+                       disposed = true;
+
+                       if (disposing) {
+                               if (backend != null)
+                                       backend.Dispose ();
+                               taskLists = null;
+                               backend = null;
+                       }
+               }
+
+               public event EventHandler BackendChanged;
+               public event EventHandler BackendChanging;
+               public event EventHandler BackendInitialized;
+               public event EventHandler BackendConfigurationRequested;
+
+               void InitializeBackend ()
+               {
+                       var node = availableBackendNodes.Single (
+                               n => n.Id == currentBackend);
+                       Logger.Info ("Using backend: {0} ({1})",
+                                    node.Data.Name, currentBackend);
+                       backend = (IBackend2)node.CreateInstance ();
+                       backend.NeedsConfiguration += delegate {
+                               if (BackendConfigurationRequested != null)
+                                       BackendConfigurationRequested (this, EventArgs.Empty);
+                       };
+                       backend.Initialized += delegate {
+                               // load data
+                               taskLists.LoadTaskLists (backend);
+                               if (BackendInitialized != null)
+                                       BackendInitialized (this, EventArgs.Empty);
+                       };
+                       
+                       try {
+                               backend.Initialize (preferences);
+                       } catch (Exception ex) {
+                               backend.Dispose ();
+                               backend = null;
+                               throw ex;
+                       }
+               }
+
+               void ThrowIfDisposed ()
+               {
+                       if (disposed)
+                               throw new ObjectDisposedException ("BackendManager");
+               }
+
+               ExtensionNodeList<BackendNode> availableBackendNodes;
+               IBackend2 backend;
+               string currentBackend;
+               IPreferences preferences;
+               TaskListCollection taskLists;
+               bool disposed;
+       }
+}
diff --git a/src/libtasque/Core/Impl/Note.cs b/src/libtasque/Core/Impl/Note.cs
new file mode 100644
index 0000000..3a12521
--- /dev/null
+++ b/src/libtasque/Core/Impl/Note.cs
@@ -0,0 +1,107 @@
+//
+// Note.cs
+//
+// Author:
+//       Antonius Riha <antoniusriha gmail com>
+//
+// Copyright (c) 2013 Antonius Riha
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using Tasque.Data;
+
+namespace Tasque.Core.Impl
+{
+       public class Note
+               : TasqueObject<INoteRepository>, INote, IInternalContainee<Task, Note>
+       {
+               public static Note CreateNote (string id, INoteRepository repository)
+               {
+                       return new Note (repository) { Id = id };
+               }
+               
+               public Note (INoteRepository repository) : base (repository)
+               {
+                       isBackendDetached = true;
+               }
+
+               public string Title {
+                       get { return title; }
+                       set {
+                               this.SetProperty<string, Note> ("Title", value, title,
+                                       x => title = x, Repository.UpdateTitle);
+                       }
+               }
+
+               public string Text {
+                       get { return text; }
+                       set {
+                               this.SetProperty<string, Note> ("Text", value, text,
+                                       x => text = x, Repository.UpdateText);
+                       }
+               }
+
+               public override bool IsBackendDetached {
+                       get { return isBackendDetached; }
+               }
+
+               public override void AttachBackend (ITasqueObject container)
+               {
+                       isBackendDetached = false;
+               }
+               
+               public override void DetachBackend (ITasqueObject container)
+               {
+                       if (!InternalContainers.Any (
+                               t => t != container && !t.IsBackendDetached))
+                               isBackendDetached = true;
+               }
+
+               public Collection<Task> InternalContainers {
+                       get {
+                               return containers ?? (containers = new Collection<Task> ());
+                       }
+               }
+
+               public override void Merge (ITasqueCore source)
+               {
+                       var sourceNote = (INoteCore)source;
+                       var wasBackendDetached = isBackendDetached;
+                       isBackendDetached = true;
+                       Text = sourceNote.Text;
+                       isBackendDetached = wasBackendDetached;
+               }
+
+               public override void Refresh () {}
+
+               IEnumerable<Task> IContainee<Task>.Containers {
+                       get { return InternalContainers; }
+               }
+
+               IEnumerable<ITaskCore> IContainee<ITaskCore>.Containers {
+                       get { return InternalContainers; }
+               }
+
+               bool isBackendDetached;
+               string title, text;
+               Collection<Task> containers;
+       }
+}
diff --git a/src/libtasque/Core/Impl/Task.cs b/src/libtasque/Core/Impl/Task.cs
new file mode 100644
index 0000000..357f941
--- /dev/null
+++ b/src/libtasque/Core/Impl/Task.cs
@@ -0,0 +1,556 @@
+//
+// Task.cs
+//
+// Original header:
+// AbstractTask.cs created with MonoDevelop
+// User: boyd at 6:52 AM 2/12/2008
+//
+// Authors:
+//       Unknown author
+//       Antonius Riha <antoniusriha gmail com>
+//
+// Copyright (c) 2013 Antonius Riha
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using Tasque.Data;
+
+namespace Tasque.Core.Impl
+{
+       using NoteCollection =
+               TasqueObjectCollection<INote, INoteCore, Task, ITaskRepository>;
+       using TaskTaskCollection =
+               TasqueObjectCollection<ITask, ITaskCore, Task, ITaskRepository>;
+
+       public class Task : TasqueObject<ITaskRepository>, ITask,
+               IInternalContainee<TaskList, Task>, IContainer<Note>,
+               IContainer<Task>, IInternalContainee<Task, Task>
+       {
+               #region Static
+
+               const string CannotBeDiscardedExMsg = "The current backend" +
+                       "doesn't allow tasks to be discarded.";
+
+               public static Task CreateTask (string id, string text,
+                       ITaskRepository taskRepo, INoteRepository noteRepo)
+               {
+                       return new Task (text, taskRepo, noteRepo) { Id = id };
+               }
+
+               public static Task CreateCompletedTask (
+                       string id, string text, DateTime completionDate,
+                       ITaskRepository taskRepo, INoteRepository noteRepo)
+               {
+                       var task = CreateTask (id, text, taskRepo, noteRepo);
+                       task.State = TaskState.Completed;
+                       task.CompletionDate = completionDate;
+                       return task;
+               }
+
+               public static Task CreateDiscardedTask (string id, string text,
+                       ITaskRepository taskRepo, INoteRepository noteRepo)
+               {
+                       var task = CreateTask (id, text, taskRepo, noteRepo);
+                       if (!task.SupportsDiscarding)
+                               throw new NotSupportedException (CannotBeDiscardedExMsg);
+                       task.State = TaskState.Discarded;
+                       return task;
+               }
+
+               #endregion
+
+               public Task (string text, ITaskRepository taskRepo,
+                            INoteRepository noteRepo) : base (taskRepo)
+               {
+                       isBackendDetached = true;
+
+                       if (NoteSupport != NoteSupport.None) {
+                               if (noteRepo == null) {
+                                       throw new ArgumentNullException ("noteRepo",
+                                               "Since this task supports adding notes " +
+                                               "an INoteRepository must be provided.");
+                               }
+                               this.noteRepo = noteRepo;
+                       }
+
+                       if (text == null)
+                               throw new ArgumentNullException ("text");
+                       Text = text;
+               }
+
+               #region Properties
+
+               /// <value>
+               /// A Task's text will be used to show the task in the main list window.
+               /// </value>
+               /// <summary>
+               /// Gets or sets the text.
+               /// </summary>
+               public string Text {
+                       get { return text; }
+                       set {
+                               var val = value.Trim ();
+                               this.SetProperty<string, Task> ("Text", val, text,
+                                       x => text = x, Repository.UpdateText);
+                       }
+               }
+
+               /// <value>
+               /// A DueDate of DateTime.MinValue indicates that a due date is not set.
+               /// </value>
+               /// <summary>
+               /// Gets or sets the due date.
+               /// </summary>
+               public DateTime DueDate {
+                       get { return dueDate; }
+                       set {
+                               this.SetProperty<DateTime, Task> ("DueDate", value, dueDate,
+                                       x => dueDate = x, Repository.UpdateDueDate);
+                       }
+               }
+
+               /// <value>
+               /// If set to CompletionDate.MinValue, the task has not been completed.
+               /// </value>
+               /// <summary>
+               /// Gets the completion date.
+               /// </summary>
+               public DateTime CompletionDate {
+                       get { return completionDate; }
+                       private set {
+                               if (value == completionDate)
+                                       return;
+
+                               Logger.Debug ("Setting new task completion date");
+                               OnPropertyChanging ("CompletionDate");
+                               completionDate = value;
+                               OnPropertyChanged ("CompletionDate");
+                       }
+               }
+
+               /// <value>
+               /// This is a convenience property which to determine whether a task is
+               /// completed.
+               /// </value>
+               /// <summary>
+               /// Gets a value indicating whether this task is completed.
+               /// </summary>
+               public bool IsComplete { get { return state == TaskState.Completed; } }
+
+               /// <value>
+               /// Backends should, by default, set the priority of a task to
+               /// TaskPriority.None.
+               /// </value>
+               /// <summary>
+               /// Gets or sets the priority.
+               /// </summary>
+               public TaskPriority Priority {
+                       get { return priority; }
+                       set {
+                               this.SetProperty<TaskPriority, Task> ("Priority", value,
+                                       priority, x => priority = x, Repository.UpdatePriority);
+                       }
+               }
+
+               /// <value>
+               /// The state of the task.
+               /// </value>
+               /// <summary>
+               /// Gets the state.
+               /// </summary>
+               public TaskState State {
+                       get { return state; }
+                       private set {
+                               if (value == state)
+                                       return;
+
+                               Logger.Debug ("Setting new task state");
+                               OnPropertyChanging ("State");
+                               state = value;
+                               OnPropertyChanged ("State");
+                       }
+               }
+
+               public bool SupportsSharingNotesWithOtherTasks {
+                       get {
+                               return ((ICollectionRepository<INoteCore, ITaskCore>)
+                                       Repository).SupportsSharingItemsWithOtherCollections;
+                       }
+               }
+               
+               /// <summary>
+               /// Gets the type of note support of this task/backend.
+               /// </summary>
+               /// <value>
+               /// The note support.
+               /// </value>
+               public NoteSupport NoteSupport {
+                       get { return Repository.NoteSupport; }
+               }
+               
+               public INote Note {
+                       get {
+                               ThrowOnSingleNoteSupport ();
+                               return note;
+                       }
+                       set {
+                               ThrowOnSingleNoteSupport ();
+                               this.SetProperty<INoteCore, Task> (
+                                       "Note", value, note, x => note = (INote)x, Repository.UpdateNote);
+                       }
+               }
+
+               /// <value>
+               /// Indicates whether any notes exist in this task.
+               /// </value>
+               /// <summary>
+               /// Gets a value indicating whether this instance has notes.
+               /// </summary>
+               public bool HasNotes {
+                       get {
+                               return NoteSupport != NoteSupport.None &&
+                                       (notes != null ? notes.Count > 0 : false);
+                       }
+               }
+
+               /// <summary>
+               /// Gets the notes associated with this task
+               /// </summary>
+               /// <value>
+               /// The notes.
+               /// </value>
+               public ObservableCollection<INote> Notes {
+                       get {
+                               if (NoteSupport == NoteSupport.None) {
+                                       throw new NotSupportedException (
+                                               "This task doesn't support notes.");
+                               } else if (NoteSupport == NoteSupport.Single) {
+                                       throw new NotSupportedException (
+                                               "This task doesn't support multiple notes. " +
+                                               "Use property Task.Note instead.");
+                               }
+                               return notes ?? (notes = new NoteCollection (this));
+                       }
+               }
+
+               /// <summary>
+               /// Gets a value indicating whether this instance can be discarded.
+               /// </summary>
+               /// <value>
+               /// <c>true</c> if this instance can be discarded; otherwise, <c>false</c>.
+               /// </value>
+               public bool SupportsDiscarding {
+                       get { return Repository.SupportsDiscarding; }
+               }
+
+               public bool SupportsNestedTasks {
+                       get { return Repository.SupportsNestedTasks; }
+               }
+
+               public bool SupportsSharingNestedTasksWithOtherTasks {
+                       get {
+                               return ((ICollectionRepository<ITaskCore, ITaskCore>)
+                                       Repository).SupportsSharingItemsWithOtherCollections;
+                       }
+               }
+
+               public bool HasNestedTasks {
+                       get {
+                               return SupportsNestedTasks &&
+                                       (nestedTasks != null ? nestedTasks.Count > 0 : false);
+                       }
+               }
+
+               public ObservableCollection<ITask> NestedTasks {
+                       get {
+                               if (!SupportsNestedTasks)
+                                       throw new NotSupportedException ("This task doesn't " +
+                                                                        "support nested tasks.");
+                               return nestedTasks ??
+                                       (nestedTasks = new TaskTaskCollection (this));
+                       }
+               }
+
+               public override bool IsBackendDetached {
+                       get { return isBackendDetached; }
+               }
+
+               #endregion // Properties
+
+               public override void AttachBackend (ITasqueObject container)
+               {
+                       isBackendDetached = false;
+                       if (HasNotes)
+                               ((NoteCollection)Notes).AttachBackend (this);
+                       if (HasNestedTasks)
+                               ((TaskTaskCollection)NestedTasks).AttachBackend (this);
+               }
+
+               public override void DetachBackend (ITasqueObject container)
+               {
+                       var noAttachedContainer = true;
+                       if (taskListContainers != null) {
+                               noAttachedContainer = !taskListContainers.Any (
+                                       l => l != container && !l.IsBackendDetached);
+                       }
+                       if (noAttachedContainer && taskContainers != null) {
+                               noAttachedContainer = !taskContainers.Any (
+                                       t => t != container && !t.IsBackendDetached);
+                       }
+
+                       if (noAttachedContainer) {
+                               if (HasNotes)
+                                       ((NoteCollection)Notes).DetachBackend (this);
+                               if (HasNestedTasks)
+                                       ((TaskTaskCollection)NestedTasks).DetachBackend (this);
+                               isBackendDetached = true;
+                       }
+               }
+
+               public INote CreateNote ()
+               {
+                       return CreateNote (null);
+               }
+
+               public INote CreateNote (string text)
+               {
+                       if (NoteSupport == NoteSupport.None)
+                               throw new NotSupportedException (
+                                       "This task doesn't support notes.");
+                       var note = new Note (noteRepo) { Text = text };
+                       if (NoteSupport == NoteSupport.Single)
+                               Note = note;
+                       else
+                               Notes.Add (note);
+                       return note;
+               }
+
+               public ITask CreateNestedTask (string text)
+               {
+                       if (!SupportsNestedTasks)
+                               throw new NotSupportedException (
+                                       "This task doesn't support nested tasks.");
+                       var task = new Task (text, Repository, noteRepo);
+                       NestedTasks.Add (task);
+                       return task;
+               }
+
+               /// <summary>
+               /// Activate (Reopen) a task that's Completed.
+               /// </summary>
+               public void Activate ()
+               {
+                       if (State != TaskState.Completed)
+                               throw new InvalidOperationException ("Only tasks that have" +
+                                       "been completed can be activated.");
+
+                       Logger.Debug ("Task.Activate ()");
+                       if (!IsBackendDetached)
+                               Repository.Activate (this);
+
+                       if (Activating != null)
+                               Activating (this, EventArgs.Empty);
+                       State = TaskState.Active;
+                       CompletionDate = DateTime.MinValue;
+                       if (Activated != null)
+                               Activated (this, EventArgs.Empty);
+               }
+
+               /// <summary>
+               /// Mark a task as completed.
+               /// </summary>
+               /// <exception cref="System.InvalidOperationException">
+               /// Thrown when the task is not active.
+               /// </exception>
+               public void Complete ()
+               {
+                       if (State != TaskState.Active)
+                               throw new InvalidOperationException (
+                                       "Only active tasks can be completed.");
+
+                       Logger.Debug ("Task.Complete ()");
+                       var completionDate = DateTime.Now;
+                       if (!IsBackendDetached)
+                               completionDate = Repository.Complete (this, completionDate);
+
+                       if (Completing != null)
+                               Completing (this, EventArgs.Empty);
+                       State = TaskState.Completed;
+                       CompletionDate = completionDate;
+                       if (Completed != null)
+                               Completed (this, EventArgs.Empty);
+               }
+
+               /// <summary>
+               /// Discard a task. This method throws, if discarding is not supported.
+               /// </summary>
+               /// <exception cref="System.NotSupportedException">
+               /// thrown when <see cref="CanBeDiscarded"/> is <c>false</c>.
+               /// </exception>
+               /// <exception cref="System.InvalidOperationException">
+               /// thrown when <see cref="IsComplete"/> is <c>true</c>.
+               /// </exception>
+               public void Discard ()
+               {
+                       if (!SupportsDiscarding)
+                               throw new NotSupportedException (CannotBeDiscardedExMsg);
+                       if (IsComplete)
+                               throw new InvalidOperationException ("A complete task" +
+                                                                    "cannot be discarded.");
+
+                       Logger.Debug ("Task.Discard ()");
+                       if (!IsBackendDetached)
+                               Repository.Discard (this);
+                       if (Discarding != null)
+                               Discarding (this, EventArgs.Empty);
+                       State = TaskState.Discarded;
+                       if (Discarded != null)
+                               Discarded (this, EventArgs.Empty);
+               }
+
+               public event EventHandler Completing, Completed, Activating,
+                       Activated, Discarding, Discarded;
+
+               public override void Refresh ()
+               {
+                       // detach all from backend
+//                     foreach (var note in Notes)
+//                             note.DetachBackend ();
+//
+//                     DetachBackend ();
+//
+//                     var notes = Repository.GetNotes (this);
+//                     Notes.Clear ();
+//                     foreach (var note in notes)
+//                             Notes.Add (note);
+//                     
+//                     AttachBackend ();
+//
+//                     foreach (var note in Notes)
+//                             note.AttachBackend ();
+               }
+
+               public override void Merge (ITasqueCore source)
+               {
+                       var sourceTask = (ITaskCore)source;
+                       var wasBackendDetached = isBackendDetached;
+                       isBackendDetached = true;
+                       DueDate = sourceTask.DueDate;
+                       Priority = sourceTask.Priority;
+                       Text = sourceTask.Text;
+                       isBackendDetached = wasBackendDetached;
+               }
+
+               #region Explicit content
+               Collection<TaskList> IInternalContainee<TaskList, Task>
+                       .InternalContainers {
+                       get { return TaskListContainers; }
+               }
+
+               Collection<Task> IInternalContainee<Task, Task>.InternalContainers {
+                       get { return TaskContainers; }
+               }
+
+               IEnumerable<ITaskListCore> IContainee<ITaskListCore>.Containers {
+                       get { return TaskListContainers; }
+               }
+
+               IEnumerable<TaskList> IContainee<TaskList>.Containers {
+                       get { return TaskListContainers; }
+               }
+
+               IEnumerable<ITaskCore> IContainee<ITaskCore>.Containers {
+                       get { return TaskContainers; }
+               }
+
+               IEnumerable<Task> IContainee<Task>.Containers {
+                       get { return TaskContainers; }
+               }
+
+               IEnumerable<Note> IContainer<Note>.Items {
+                       get {
+                               IEnumerable<INote> notes = this.notes;
+                               if (!HasNotes)
+                                       notes = Enumerable.Empty<INote> ();
+                               foreach (var item in notes)
+                                       yield return (Note)item;
+                       }
+               }
+
+               IEnumerable<Task> IContainer<Task>.Items {
+                       get {
+                               IEnumerable<ITask> tasks = nestedTasks;
+                               if (!HasNestedTasks)
+                                       tasks = Enumerable.Empty<ITask> ();
+                               foreach (var item in tasks)
+                                       yield return (Task)item;
+                       }
+               }
+
+               IEnumerable<ITaskListCore> ITaskCore.TaskListContainers {
+                       get { return TaskListContainers; }
+               }
+
+               IEnumerable<ITaskCore> ITaskCore.TaskContainers {
+                       get { return TaskContainers; }
+               }
+               #endregion
+
+               Collection<TaskList> TaskListContainers {
+                       get {
+                               return taskListContainers ?? (
+                                       taskListContainers = new Collection<TaskList> ());
+                       }
+               }
+
+               Collection<Task> TaskContainers {
+                       get {
+                               return taskContainers ?? (
+                                       taskContainers = new Collection<Task> ());
+                       }
+               }
+
+               void ThrowOnSingleNoteSupport ()
+               {
+                       if (NoteSupport == NoteSupport.None) {
+                               throw new NotSupportedException (
+                                       "This task doesn't support notes.");
+                       } else if (NoteSupport == NoteSupport.Multiple) {
+                               throw new NotSupportedException (
+                                       "This task supports multiple notes. Use " +
+                                       "property Task.Notes instead.");
+                       }
+               }
+
+               bool isBackendDetached;
+               string text;
+               DateTime dueDate, completionDate;
+               TaskPriority priority;
+               TaskState state;
+               INote note;
+               NoteCollection notes;
+               TaskTaskCollection nestedTasks;
+               Collection<TaskList> taskListContainers;
+               Collection<Task> taskContainers;
+               INoteRepository noteRepo;
+       }
+}
diff --git a/src/libtasque/Core/Impl/TaskList.cs b/src/libtasque/Core/Impl/TaskList.cs
new file mode 100644
index 0000000..cad7328
--- /dev/null
+++ b/src/libtasque/Core/Impl/TaskList.cs
@@ -0,0 +1,269 @@
+//
+// TaskList.cs
+//
+// Author:
+//       Antonius Riha <antoniusriha gmail com>
+//
+// Copyright (c) 2013 Antonius Riha
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using Tasque.Data;
+
+namespace Tasque.Core.Impl
+{
+       using TaskListTaskCollection =
+               TasqueObjectCollection<ITask, ITaskCore, TaskList, ITaskListRepository>;
+
+       public class TaskList : TasqueObject<ITaskListRepository>, ITaskList,
+               ICollection<ITask>, IContainer<Task>, INotifyCollectionChanged
+       {
+               const string ItemExistsExMsg = "The specified Task exists already.";
+
+               public static TaskList CreateTaskList (
+                       string id, string name, ITaskListRepository taskListRepo,
+                       ITaskRepository taskRepo, INoteRepository noteRepo)
+               {
+                       return new TaskList (name, taskListRepo, taskRepo, noteRepo) {
+                               Id = id
+                       };
+               }
+
+               public static ITaskListCore CreateSmartTaskList (
+                       string id, string name, ITaskListRepository taskListRepo)
+               {
+                       return new TaskList (name, taskListRepo) { Id = id };
+               }
+
+               public TaskList (string name, ITaskListRepository taskListRepo,
+                       ITaskRepository taskRepo, INoteRepository noteRepo)
+                       : base (taskListRepo)
+               {
+                       if (taskRepo == null)
+                               throw new ArgumentNullException ("taskRepo");
+                       this.taskRepo = taskRepo;
+                       this.noteRepo = noteRepo;
+
+                       isBackendDetached = true;
+
+                       Name = name;
+               }
+
+               public TaskList (string name, ITaskListRepository taskListRepo,
+                                ITaskRepository taskRepo)
+                       : this (name, taskListRepo, taskRepo, null) {}
+
+               TaskList (string name, ITaskListRepository taskListRepo)
+                       : base (taskListRepo)
+               {
+                       isBackendDetached = true;
+                       ListType = TaskListType.Smart;
+                       Name = name;
+               }
+
+               public int Count { get { return Tasks.Count; } }
+
+               public bool IsReadOnly {
+                       get { return ListType == TaskListType.Smart; }
+               }
+
+               public bool SupportsSharingTasksWithOtherTaskLists {
+                       get { return Repository.SupportsSharingItemsWithOtherCollections; }
+               }
+
+               public bool CanChangeName {
+                       get { return Repository.CanChangeName (this); }
+               }
+
+               /// <summary>
+               /// Gets or sets the name.
+               /// </summary>
+               /// <value>
+               /// The name.
+               /// </value>
+               /// <exception cref="System.InvalidOperationException">
+               /// thrown when <see cref="CanChangeName"/> is <c>false</c>.
+               /// </exception>
+               /// <exception cref="System.ArgumentNullException">
+               /// thrown when the value is <c>null</c>.
+               /// </exception>
+               /// <exception cref="System.ArgumentException">
+               /// thrown when the name is an empty string or consists only of white
+               /// space characters.
+               /// </exception>
+               public string Name {
+                       get { return name; }
+                       set {
+                               if (!CanChangeName)
+                                       throw new InvalidOperationException ("Cannot change " +
+                                               "the name because CanChangeName is false.");
+                               if (value == null)
+                                       throw new ArgumentNullException ("name");
+                               if (string.IsNullOrWhiteSpace (value))
+                                       throw new ArgumentException (
+                                               "Must not be empty or white space", "name");
+
+                               this.SetProperty<string, TaskList> ("Name", value,
+                                       name, x => name = x, Repository.UpdateName);
+                       }
+               }
+
+               public TaskListType ListType { get; private set; }
+
+               public override bool IsBackendDetached {
+                       get { return isBackendDetached; }
+               }
+
+               public override void AttachBackend (ITasqueObject container)
+               {
+                       isBackendDetached = false;
+                       Tasks.AttachBackend (this);
+               }
+
+               public override void DetachBackend (ITasqueObject container)
+               {
+                       Tasks.DetachBackend (this);
+                       isBackendDetached = true;
+               }
+               
+               /// <summary>
+               /// Creates a new task and adds it to this list.
+               /// </summary>
+               /// <returns>
+               /// The task.
+               /// </returns>
+               /// <param name='name'>
+               /// The text of the task.
+               /// </param>
+               public ITask CreateTask (string text)
+               {
+                       throw new NotImplementedException ();
+               }
+
+               public void Add (ITask item)
+               {
+                       if (!IsBackendDetached)
+                               ThrowIfIsReadOnly ();
+                       Tasks.Add (item);
+               }
+
+               public void Clear ()
+               {
+                       if (!IsBackendDetached)
+                               ThrowIfIsReadOnly ();
+                       Tasks.Clear ();
+               }
+
+               public bool Contains (ITask item)
+               {
+                       return Tasks.Contains (item);
+               }
+
+               public void CopyTo (ITask [] array, int arrayIndex)
+               {
+                       Tasks.CopyTo (array, arrayIndex);
+               }
+
+               public IEnumerator<ITask> GetEnumerator ()
+               {
+                       return Tasks.GetEnumerator ();
+               }
+
+               public bool Remove (ITask item)
+               {
+                       if (!IsBackendDetached)
+                               ThrowIfIsReadOnly ();
+                       return Tasks.Remove (item);
+               }
+
+               public override void Refresh ()
+               {
+//                     // detach all from backend
+//                     foreach (var task in this) {
+//                             foreach (var note in task.Notes)
+//                                     note.DetachBackend ();
+//                             task.DetachBackend ();
+//                     }
+//                     DetachBackend ();
+//                     
+//                     var tasks = Repository.GetTasks (this);
+//                     Clear ();
+//                     foreach (var task in Tasks)
+//                             Add (task);
+//                     
+//                     AttachBackend ();
+//                     foreach (var task in this) {
+//                             task.AttachBackend ();
+//                             foreach (var note in task.Notes)
+//                                     note.AttachBackend ();
+//                     }
+               }
+
+               public override void Merge (ITasqueCore source)
+               {
+                       var sourceTaskList = (ITaskListCore)source;
+                       var wasBackendDetached = isBackendDetached;
+                       isBackendDetached = true;
+                       if (CanChangeName)
+                               Name = sourceTaskList.Name;
+                       isBackendDetached = wasBackendDetached;
+               }
+
+               public event NotifyCollectionChangedEventHandler CollectionChanged {
+                       add { Tasks.CollectionChanged += value; }
+                       remove { Tasks.CollectionChanged -= value; }
+               }
+
+               #region Explicit content
+               IEnumerator IEnumerable.GetEnumerator ()
+               {
+                       return GetEnumerator ();
+               }
+
+               IEnumerable<Task> IContainer<Task>.Items {
+                       get {
+                               foreach (var item in this)
+                                       yield return (Task)item;
+                       }
+               }
+               #endregion
+
+               TaskListTaskCollection Tasks {
+                       get {
+                               return tasks ?? (tasks = new TaskListTaskCollection (this));
+                       }
+               }
+
+               void ThrowIfIsReadOnly ()
+               {
+                       if (IsReadOnly)
+                               throw new InvalidOperationException (
+                                       "This collection is read-only.");
+               }
+
+               bool isBackendDetached;
+               string name;
+               TaskListTaskCollection tasks;
+               INoteRepository noteRepo;
+               ITaskRepository taskRepo;
+       }
+}
diff --git a/src/libtasque/Core/Impl/TasqueObject.cs b/src/libtasque/Core/Impl/TasqueObject.cs
new file mode 100644
index 0000000..eb68665
--- /dev/null
+++ b/src/libtasque/Core/Impl/TasqueObject.cs
@@ -0,0 +1,92 @@
+//
+// TasqueObject.cs
+//
+// Author:
+//       Antonius Riha <antoniusriha gmail com>
+//
+// Copyright (c) 2013 Antonius Riha
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using System.ComponentModel;
+using Tasque.Data;
+
+namespace Tasque.Core.Impl
+{
+       public abstract class TasqueObject<TRepo> : IInternalTasqueObject,
+               IBackendDetachable, IIdEditable<ITasqueObject>, INotifying
+               where TRepo : IRepository
+       {
+               protected TasqueObject (TRepo repository)
+               {
+                       if (repository == null)
+                               throw new ArgumentNullException ("repository");
+                       Repository = repository;
+               }
+
+               /// <summary>
+               /// Gets the identifier. The id is managed by the backend and thus not
+               /// editable from the front end.
+               /// </summary>
+               /// <value>
+               /// The identifier.
+               /// </value>
+               public string Id { get; protected set; }
+
+               public TRepo Repository { get; private set; }
+
+               public abstract bool IsBackendDetached { get; }
+               public abstract void DetachBackend (ITasqueObject container);
+               public abstract void AttachBackend (ITasqueObject container);
+               public abstract void Merge (ITasqueCore source);
+               public abstract void Refresh ();
+
+               protected void OnPropertyChanged (string propertyName)
+               {
+                       if (PropertyChanged != null)
+                               PropertyChanged (
+                                       this, new PropertyChangedEventArgs (propertyName));
+               }
+               
+               protected void OnPropertyChanging (string propertyName)
+               {
+                       if (PropertyChanging != null)
+                               PropertyChanging (
+                                       this, new PropertyChangingEventArgs (propertyName));
+               }
+
+               public event PropertyChangedEventHandler PropertyChanged;
+               public event PropertyChangingEventHandler PropertyChanging;
+
+               void INotifying.OnPropertyChanged (string propertyName)
+               {
+                       OnPropertyChanged (propertyName);
+               }
+               
+               void INotifying.OnPropertyChanging (string propertyName)
+               {
+                       OnPropertyChanging (propertyName);
+               }
+
+               void IIdEditable<ITasqueObject>.SetId (string id)
+               {
+                       Id = id;
+               }
+       }
+}
diff --git a/src/libtasque/Core/Impl/TasqueObjectCollection.cs 
b/src/libtasque/Core/Impl/TasqueObjectCollection.cs
new file mode 100644
index 0000000..d0e982b
--- /dev/null
+++ b/src/libtasque/Core/Impl/TasqueObjectCollection.cs
@@ -0,0 +1,157 @@
+//
+// TasqueObjectCollection.cs
+//
+// Author:
+//       Antonius Riha <antoniusriha gmail com>
+//
+// Copyright (c) 2013 Antonius Riha
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using System.Collections.ObjectModel;
+using System.Linq;
+using Tasque.Data;
+
+namespace Tasque.Core.Impl
+{
+       public class TasqueObjectCollection<T, TCore, TContainer, TContainerRepo>
+               : ObservableCollection<T>, IBackendDetachable
+               where TCore : ITasqueCore
+               where T : TCore, ITasqueObject
+               where TContainerRepo : ICollectionRepository<TCore, TContainer>
+               where TContainer : TasqueObject<TContainerRepo>, IContainer<T>
+       {
+               const string ItemExistsExMsg = "The specified item exists already.";
+
+               public TasqueObjectCollection (TContainer container)
+               {
+                       if (container == null)
+                               throw new ArgumentNullException ("container");
+                       this.container = container;
+                       IsBackendDetached = container.IsBackendDetached;
+
+                       foreach (var item in container.Repository.GetAll (container)) {
+                               var existingItem = ((IInternalContainee<TContainer, T>)item)
+                                       .Containers.SelectMany (c => c.Items)
+                                       .FirstOrDefault (i => i.Id == item.Id);
+                               if (existingItem == null)
+                                       Add ((T)item);
+                               else {
+                                       ((IInternalTasqueObject)existingItem).Merge (item);
+                                       Add (existingItem);
+                               }
+                       }
+               }
+
+               public bool SupportsSharingItemsWithOtherCollections {
+                       get {
+                               return container.Repository
+                                       .SupportsSharingItemsWithOtherCollections;
+                       }
+               }
+
+               public bool IsBackendDetached { get; private set; }
+
+               public void AttachBackend (ITasqueObject container)
+               {
+                       IsBackendDetached = false;
+                       foreach (var item in this)
+                               ((IBackendDetachable)item).AttachBackend (container);
+               }
+
+               public void DetachBackend (ITasqueObject container)
+               {
+                       foreach (var item in this)
+                               ((IBackendDetachable)item).DetachBackend (container);
+                       IsBackendDetached = true;
+               }
+
+               protected override void ClearItems ()
+               {
+                       if (!IsBackendDetached)
+                               container.Repository.ClearAll (container);
+                       foreach (var item in this) {
+                               var containee = (IInternalContainee<TContainer, T>)item;
+                               containee.InternalContainers.Remove (container);
+                               if (containee.InternalContainers.Count == 0)
+                                       ((IBackendDetachable)item).DetachBackend (container);
+                       }
+                       base.ClearItems ();
+               }
+
+               protected override void InsertItem (int index, T item)
+               {
+                       AddObject (item);
+                       base.InsertItem (index, item);
+               }
+
+               protected override void RemoveItem (int index)
+               {
+                       var oldItem = this [index];
+                       RemoveObject (oldItem);
+                       base.RemoveItem (index);
+               }
+
+               protected override void SetItem (int index, T item)
+               {
+                       var oldItem = this [index];
+                       RemoveObject (oldItem);
+                       AddObject (item);
+                       base.SetItem (index, item);
+               }
+
+               void AddObject (T item)
+               {
+                       if (Contains (item))
+                               throw new ArgumentException (ItemExistsExMsg, "item");
+                       if (!IsBackendDetached)
+                               AddObjectToRepo (item);
+                       ((IInternalContainee<TContainer, T>)item)
+                               .InternalContainers.Add (container);
+               }
+
+               void AddObjectToRepo (T item)
+               {
+                       if (!SupportsSharingItemsWithOtherCollections)
+                               container.Repository.AddNew (container, item);
+                       else {
+                               var itemHasContainers = ((IInternalContainee<TContainer, T>)
+                                                        item).InternalContainers.Count > 0;
+                               if (itemHasContainers)
+                                       container.Repository.Add (container, item);
+                               else
+                                       container.Repository.AddNew (container, item);
+                       }
+                       ((IBackendDetachable)item).AttachBackend (container);
+               }
+
+               void RemoveObject (T item)
+               {
+                       var containee = (IInternalContainee<TContainer, T>)item;
+                       if (!IsBackendDetached) {
+                               container.Repository.Remove (container, item);
+                               if (containee.InternalContainers.Count == 1)
+                                       ((IBackendDetachable)item).DetachBackend (container);
+                       }
+                       containee.InternalContainers.Remove (container);
+               }
+
+               TContainer container;
+       }
+}
diff --git a/src/libtasque/IBackendPreferences.cs b/src/libtasque/Core/TaskListType.cs
similarity index 88%
copy from src/libtasque/IBackendPreferences.cs
copy to src/libtasque/Core/TaskListType.cs
index 1f1a236..01686ff 100644
--- a/src/libtasque/IBackendPreferences.cs
+++ b/src/libtasque/Core/TaskListType.cs
@@ -1,21 +1,21 @@
-// 
-// IBackendPreferences.cs
-//  
+//
+// TaskListType.cs
+//
 // Author:
 //       Antonius Riha <antoniusriha gmail com>
-// 
-// Copyright (c) 2012 Antonius Riha
-// 
+//
+// Copyright (c) 2013 Antonius Riha
+//
 // Permission is hereby granted, free of charge, to any person obtaining a copy
 // of this software and associated documentation files (the "Software"), to deal
 // in the Software without restriction, including without limitation the rights
 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 // copies of the Software, and to permit persons to whom the Software is
 // furnished to do so, subject to the following conditions:
-// 
+//
 // The above copyright notice and this permission notice shall be included in
 // all copies or substantial portions of the Software.
-// 
+//
 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -23,10 +23,11 @@
 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 // THE SOFTWARE.
-
-namespace Tasque.Backends
+namespace Tasque.Core
 {
-       public interface IBackendPreferences
+       public enum TaskListType
        {
+               Regular,
+               Smart
        }
 }
diff --git a/src/libtasque/CategoryComparer.cs b/src/libtasque/Core/TaskState.cs
similarity index 57%
copy from src/libtasque/CategoryComparer.cs
copy to src/libtasque/Core/TaskState.cs
index b81fcfa..e3105c6 100644
--- a/src/libtasque/CategoryComparer.cs
+++ b/src/libtasque/Core/TaskState.cs
@@ -1,10 +1,15 @@
 //
-// CategoryComparer.cs
+// TaskState.cs
 //
-// Author:
+// Original header:
+// TaskState.cs created with MonoDevelop
+// User: boyd at 8:37 AM 2/12/2008
+//
+// Authors:
+//       Unknown author
 //       Antonius Riha <antoniusriha gmail com>
 //
-// Copyright (c) 2012 Antonius Riha
+// Copyright (c) 2013 Antonius Riha
 //
 // Permission is hereby granted, free of charge, to any person obtaining a copy
 // of this software and associated documentation files (the "Software"), to deal
@@ -23,23 +28,30 @@
 // 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.Generic;
-
-namespace Tasque
+namespace Tasque.Core
 {
-       public class CategoryComparer : Comparer<ICategory>
+       /// <summary>
+       /// Provides information about the state of a task.
+       /// </summary>
+       public enum TaskState
        {
-               public override int Compare (ICategory x, ICategory y)
-               {
-                       if (x == null || y == null)
-                               return 0;
-                       
-                       if (x is AllCategory)
-                               return -1;
-                       else if (y is AllCategory)
-                               return 1;
-                       
-                       return (x.Name.CompareTo (y.Name));
-               }
+               /// <summary>
+               /// A task that has not been completed.
+               /// </summary>
+               Active,
+               
+               /// <summary>
+               /// A completed task.
+               /// </summary>
+               Completed,
+               
+               /// <summary>
+               /// A tasks that's discarded. This is used when tasks are being put into
+               /// the trash bin, which may be supported by the alien backend or proxied
+               /// locally (if not supported by the alien backend). As soon as the task
+               /// is actually deleted from the backend system, the task should really
+               /// be deleted.
+               /// </summary>
+               Discarded
        }
 }
diff --git a/src/libtasque/TaskComparer.cs b/src/libtasque/Data/BackendExtensionAttribute.cs
similarity index 65%
copy from src/libtasque/TaskComparer.cs
copy to src/libtasque/Data/BackendExtensionAttribute.cs
index 1285fe1..0541ca9 100644
--- a/src/libtasque/TaskComparer.cs
+++ b/src/libtasque/Data/BackendExtensionAttribute.cs
@@ -1,10 +1,10 @@
 //
-// TaskComparer.cs
+// BackendExtensionAttribute.cs
 //
 // Author:
 //       Antonius Riha <antoniusriha gmail com>
 //
-// Copyright (c) 2012 Antonius Riha
+// Copyright (c) 2013 Antonius Riha
 //
 // Permission is hereby granted, free of charge, to any person obtaining a copy
 // of this software and associated documentation files (the "Software"), to deal
@@ -23,18 +23,28 @@
 // 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.Generic;
+using Mono.Addins;
 
-namespace Tasque
+namespace Tasque.Data
 {
-       public class TaskComparer : Comparer<ITask>
+       public class BackendExtensionAttribute : CustomExtensionAttribute
        {
-               public override int Compare (ITask x, ITask y)
+               public BackendExtensionAttribute () {}
+               
+               public BackendExtensionAttribute ([NodeAttribute ("Name")] string name)
                {
-                       if (x == null || y == null)
-                               return 0;
-                       
-                       return (x.CompareTo (y));
+                       Name = name;
                }
+
+               /// <summary>
+               /// 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.
+               /// </summary>
+               /// <value>
+               /// The name.
+               /// </value>
+               [NodeAttribute]
+               public string Name { get; set; }
        }
 }
diff --git a/src/libtasque/Data/BackendInitializationException.cs 
b/src/libtasque/Data/BackendInitializationException.cs
new file mode 100644
index 0000000..f1978e1
--- /dev/null
+++ b/src/libtasque/Data/BackendInitializationException.cs
@@ -0,0 +1,68 @@
+//
+// BackendInitializationException.cs
+//
+// Author:
+//       Antonius Riha <antoniusriha gmail com>
+//
+// Copyright (c) 2013 Antonius Riha
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using System.Runtime.Serialization;
+
+namespace Tasque.Data
+{
+       
+       [Serializable]
+       public class BackendInitializationException : Exception
+       {
+               /// <summary>
+               /// Initializes a new instance of the <see cref="T:BackendInitializationException"/> class
+               /// </summary>
+               public BackendInitializationException ()
+               {
+               }
+               
+               /// <summary>
+               /// Initializes a new instance of the <see cref="T:BackendInitializationException"/> class
+               /// </summary>
+               /// <param name="message">A <see cref="T:System.String"/> that describes the exception. 
</param>
+               public BackendInitializationException (string message) : base (message)
+               {
+               }
+               
+               /// <summary>
+               /// Initializes a new instance of the <see cref="T:BackendInitializationException"/> class
+               /// </summary>
+               /// <param name="message">A <see cref="T:System.String"/> that describes the exception. 
</param>
+               /// <param name="inner">The exception that is the cause of the current exception. </param>
+               public BackendInitializationException (string message, Exception inner) : base (message, 
inner)
+               {
+               }
+               
+               /// <summary>
+               /// Initializes a new instance of the <see cref="T:BackendInitializationException"/> class
+               /// </summary>
+               /// <param name="context">The contextual information about the source or destination.</param>
+               /// <param name="info">The object that holds the serialized object data.</param>
+               protected BackendInitializationException (SerializationInfo info, StreamingContext context) : 
base (info, context)
+               {
+               }
+       }
+}
diff --git a/src/libtasque/TaskComparer.cs b/src/libtasque/Data/Extensions.cs
similarity index 75%
copy from src/libtasque/TaskComparer.cs
copy to src/libtasque/Data/Extensions.cs
index 1285fe1..8764f77 100644
--- a/src/libtasque/TaskComparer.cs
+++ b/src/libtasque/Data/Extensions.cs
@@ -1,10 +1,10 @@
 //
-// TaskComparer.cs
+// Extensions.cs
 //
 // Author:
 //       Antonius Riha <antoniusriha gmail com>
 //
-// Copyright (c) 2012 Antonius Riha
+// Copyright (c) 2013 Antonius Riha
 //
 // Permission is hereby granted, free of charge, to any person obtaining a copy
 // of this software and associated documentation files (the "Software"), to deal
@@ -23,18 +23,20 @@
 // 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.Generic;
+using System;
+using Tasque.Core.Impl;
 
-namespace Tasque
+namespace Tasque.Data
 {
-       public class TaskComparer : Comparer<ITask>
+       public static class Extensions
        {
-               public override int Compare (ITask x, ITask y)
+               public static void SetId (this ITasqueCore source, string id)
                {
-                       if (x == null || y == null)
-                               return 0;
-                       
-                       return (x.CompareTo (y));
+                       if (source == null)
+                               throw new NullReferenceException ("source");
+                       var item = source as IIdEditable<ITasqueCore>;
+                       if (item != null)
+                               item.SetId (id);
                }
        }
 }
diff --git a/src/libtasque/IBackend.cs b/src/libtasque/Data/IBackend.cs
similarity index 75%
rename from src/libtasque/IBackend.cs
rename to src/libtasque/Data/IBackend.cs
index e8ab0d3..394f08c 100644
--- a/src/libtasque/IBackend.cs
+++ b/src/libtasque/Data/IBackend.cs
@@ -6,19 +6,15 @@ using System.Collections.Generic;
 
 namespace Tasque.Backends
 {
-       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 interface IBackend : IDisposable
        {
-               event BackendInitializedHandler BackendInitialized;
-               event BackendSyncStartedHandler BackendSyncStarted;
-               event BackendSyncFinishedHandler BackendSyncFinished;
+               event EventHandler BackendInitialized;
+               event EventHandler BackendSyncStarted;
+               event EventHandler BackendSyncFinished;
 
                #region Properties
                /// <value>
@@ -34,15 +30,15 @@ namespace Tasque.Backends
                /// <value>
                /// All the tasks provided by the backend.
                /// </value>
-               ICollection<ITask> Tasks
+               ICollection<Task> Tasks
                {
                        get;
                }
                
                /// <value>
-               /// This returns all the ICategory items from the backend.
+               /// This returns all the ITaskList items from the backend.
                /// </value>
-               ICollection<ICategory> Categories
+               ICollection<TaskList> TaskLists
                {
                        get;
                }
@@ -78,15 +74,15 @@ namespace Tasque.Backends
                /// <summary>
                /// Create a new task.
                /// </summary>
-               ITask CreateTask (string taskName, ICategory category);
+               Task CreateTask (string taskName, TaskList list);
 
                /// <summary>
                /// Deletes the specified task.
                /// </summary>
                /// <param name="task">
-               /// A <see cref="ITask"/>
+               /// A <see cref="Task"/>
                /// </param>
-               void DeleteTask (ITask task);
+               void DeleteTask (Task task);
                
                /// <summary>
                /// Refreshes the backend.
diff --git a/src/libtasque/Data/IBackend2.cs b/src/libtasque/Data/IBackend2.cs
new file mode 100644
index 0000000..a93ad7b
--- /dev/null
+++ b/src/libtasque/Data/IBackend2.cs
@@ -0,0 +1,94 @@
+//
+// IBackend.cs
+//
+// Author:
+//       Antonius Riha <antoniusriha gmail com>
+//
+// Copyright (c) 2013 Antonius Riha
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using System.Collections.Generic;
+using Mono.Addins;
+
+namespace Tasque.Data
+{
+       [TypeExtensionPoint (ExtensionAttributeType =
+                            typeof (BackendExtensionAttribute))]
+       public interface IBackend2 : IDisposable,
+               IRepositoryProvider<INoteRepository>,
+               IRepositoryProvider<ITaskListRepository>,
+               IRepositoryProvider<ITaskRepository>
+       {
+               bool IsConfigured { get; }
+               bool IsInitialized { get; }
+               IBackendPreferences Preferences { get; }
+
+               /// <summary>
+               /// Initializes the backend.
+               /// </summary>
+               /// <param name='preferences'>
+               /// An object to access Tasque preferences.
+               /// </param>
+               /// <exception cref="T:Tasque.BackendInitializationException">
+               /// thrown when the initialization of the backend fails.
+               /// </exception>
+               void Initialize (IPreferences preferences);
+
+               /// <summary>
+               /// Gets all task lists populated with tasks, which in turn are
+               /// populated with notes and possibly nested tasks.
+               /// </summary>
+               /// <returns>
+               /// The lists.
+               /// </returns>
+               /// <exception cref="T:Tasque.TransactionException">
+               /// thrown when the transaction failed to commit on the backend
+               /// </exception>
+               IEnumerable<ITaskListCore> GetAll ();
+
+               ITaskListCore GetBy (string id);
+               
+               /// <summary>
+               /// Create the specified task list on the backend.
+               /// </summary>
+               /// <param name='item'>
+               /// The list to create.
+               /// </param>
+               /// <exception cref="T:Tasque.TransactionException">
+               /// thrown when the transaction failed to commit on the backend
+               /// </exception>
+               void Create (ITaskListCore taskList);
+               
+               /// <summary>
+               /// Delete the specified task list.
+               /// </summary>
+               /// <param name='item'>
+               /// The list.
+               /// </param>
+               /// <exception cref="T:Tasque.TransactionException">
+               /// thrown when the transaction failed to commit on the backend
+               /// </exception>
+               void Delete (ITaskListCore taskList);
+
+               event EventHandler Disposed;
+               event EventHandler Initialized;
+               event EventHandler NeedsConfiguration;
+       }
+}
diff --git a/src/libtasque/IBackendPreferences.cs b/src/libtasque/Data/IBackendPreferences.cs
similarity index 97%
copy from src/libtasque/IBackendPreferences.cs
copy to src/libtasque/Data/IBackendPreferences.cs
index 1f1a236..6ffc2a1 100644
--- a/src/libtasque/IBackendPreferences.cs
+++ b/src/libtasque/Data/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.Data
 {
        public interface IBackendPreferences
        {
diff --git a/src/libtasque/Data/ICollectionRepository.cs b/src/libtasque/Data/ICollectionRepository.cs
new file mode 100644
index 0000000..292d622
--- /dev/null
+++ b/src/libtasque/Data/ICollectionRepository.cs
@@ -0,0 +1,77 @@
+//
+// ICollectionRepository.cs
+//
+// Author:
+//       Antonius Riha <antoniusriha gmail com>
+//
+// Copyright (c) 2013 Antonius Riha
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System.Collections.Generic;
+
+namespace Tasque.Data
+{
+       public interface ICollectionRepository<T, in TContainer> : IRepository
+               where T : ITasqueCore
+               where TContainer : ITasqueCore
+       {
+               /// <summary>
+               /// Determines whether the specified collection instance can share
+               /// items with other collections or if an item belongs to only one
+               /// collection instance at most. NOTE: If this returns false for an
+               /// instance (or for all instances of the type), the mehtod
+               /// <see cref="Add (T, TContainer)"/> will never be called for this
+               /// instance (or for all instances of the type). Instead, each addition
+               /// of a new item will be made through
+               /// <see cref="AddNew (T, TContainer)"/>.
+               /// </summary>
+               /// <returns>
+               /// <c>true</c> if the specified instance can share items with other
+               /// collections; otherwise, <c>false</c>.
+               /// </returns>
+               bool SupportsSharingItemsWithOtherCollections { get; }
+
+               IEnumerable<T> GetAll (TContainer container);
+               T GetBy (TContainer container, string id);
+               
+               /// <summary>
+               /// Add an existing item to the container.
+               /// </summary>
+               /// <param name='item'>
+               /// Item.
+               /// </param>
+               /// <param name='container'>
+               /// Container.
+               /// </param>
+               void Add (TContainer container, T item);
+               
+               /// <summary>
+               /// Add a new item to the container.
+               /// </summary>
+               /// <param name='item'>
+               /// Item.
+               /// </param>
+               /// <param name='container'>
+               /// Container.
+               /// </param>
+               void AddNew (TContainer container, T item);
+               void Remove (TContainer container, T item);
+               void ClearAll (TContainer container);
+       }
+}
diff --git a/src/libtasque/IBackendPreferences.cs b/src/libtasque/Data/INoteRepository.cs
similarity index 81%
copy from src/libtasque/IBackendPreferences.cs
copy to src/libtasque/Data/INoteRepository.cs
index 1f1a236..e41392c 100644
--- a/src/libtasque/IBackendPreferences.cs
+++ b/src/libtasque/Data/INoteRepository.cs
@@ -1,21 +1,21 @@
-// 
-// IBackendPreferences.cs
-//  
+//
+// INoteRepository.cs
+//
 // Author:
 //       Antonius Riha <antoniusriha gmail com>
-// 
-// Copyright (c) 2012 Antonius Riha
-// 
+//
+// Copyright (c) 2013 Antonius Riha
+//
 // Permission is hereby granted, free of charge, to any person obtaining a copy
 // of this software and associated documentation files (the "Software"), to deal
 // in the Software without restriction, including without limitation the rights
 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 // copies of the Software, and to permit persons to whom the Software is
 // furnished to do so, subject to the following conditions:
-// 
+//
 // The above copyright notice and this permission notice shall be included in
 // all copies or substantial portions of the Software.
-// 
+//
 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -23,10 +23,11 @@
 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 // THE SOFTWARE.
-
-namespace Tasque.Backends
+namespace Tasque.Data
 {
-       public interface IBackendPreferences
+       public interface INoteRepository : IRepository
        {
+               string UpdateTitle (INoteCore note, string title);
+               string UpdateText (INoteCore note, string text);
        }
 }
diff --git a/src/libtasque/IBackendPreferences.cs b/src/libtasque/Data/IRepository.cs
similarity index 87%
copy from src/libtasque/IBackendPreferences.cs
copy to src/libtasque/Data/IRepository.cs
index 1f1a236..a64506b 100644
--- a/src/libtasque/IBackendPreferences.cs
+++ b/src/libtasque/Data/IRepository.cs
@@ -1,21 +1,21 @@
-// 
-// IBackendPreferences.cs
-//  
+//
+// IRepository.cs
+//
 // Author:
 //       Antonius Riha <antoniusriha gmail com>
-// 
-// Copyright (c) 2012 Antonius Riha
-// 
+//
+// Copyright (c) 2013 Antonius Riha
+//
 // Permission is hereby granted, free of charge, to any person obtaining a copy
 // of this software and associated documentation files (the "Software"), to deal
 // in the Software without restriction, including without limitation the rights
 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 // copies of the Software, and to permit persons to whom the Software is
 // furnished to do so, subject to the following conditions:
-// 
+//
 // The above copyright notice and this permission notice shall be included in
 // all copies or substantial portions of the Software.
-// 
+//
 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -23,10 +23,7 @@
 // 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.Backends
+namespace Tasque.Data
 {
-       public interface IBackendPreferences
-       {
-       }
+       public interface IRepository {}
 }
diff --git a/src/libtasque/IBackendPreferences.cs b/src/libtasque/Data/IRepositoryProvider.cs
similarity index 84%
copy from src/libtasque/IBackendPreferences.cs
copy to src/libtasque/Data/IRepositoryProvider.cs
index 1f1a236..c6159a7 100644
--- a/src/libtasque/IBackendPreferences.cs
+++ b/src/libtasque/Data/IRepositoryProvider.cs
@@ -1,21 +1,21 @@
-// 
-// IBackendPreferences.cs
-//  
+//
+// IRepositoryProvider.cs
+//
 // Author:
 //       Antonius Riha <antoniusriha gmail com>
-// 
-// Copyright (c) 2012 Antonius Riha
-// 
+//
+// Copyright (c) 2013 Antonius Riha
+//
 // Permission is hereby granted, free of charge, to any person obtaining a copy
 // of this software and associated documentation files (the "Software"), to deal
 // in the Software without restriction, including without limitation the rights
 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 // copies of the Software, and to permit persons to whom the Software is
 // furnished to do so, subject to the following conditions:
-// 
+//
 // The above copyright notice and this permission notice shall be included in
 // all copies or substantial portions of the Software.
-// 
+//
 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -23,10 +23,11 @@
 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 // THE SOFTWARE.
-
-namespace Tasque.Backends
+namespace Tasque.Data
 {
-       public interface IBackendPreferences
+       public interface IRepositoryProvider<out TRepo>
+               where TRepo : IRepository
        {
+               TRepo Repository { get; }
        }
 }
diff --git a/src/libtasque/TaskComparer.cs b/src/libtasque/Data/ITaskListRepository.cs
similarity index 80%
copy from src/libtasque/TaskComparer.cs
copy to src/libtasque/Data/ITaskListRepository.cs
index 1285fe1..e16b8b5 100644
--- a/src/libtasque/TaskComparer.cs
+++ b/src/libtasque/Data/ITaskListRepository.cs
@@ -1,10 +1,10 @@
 //
-// TaskComparer.cs
+// ITaskListRepository.cs
 //
 // Author:
 //       Antonius Riha <antoniusriha gmail com>
 //
-// Copyright (c) 2012 Antonius Riha
+// Copyright (c) 2013 Antonius Riha
 //
 // Permission is hereby granted, free of charge, to any person obtaining a copy
 // of this software and associated documentation files (the "Software"), to deal
@@ -23,18 +23,12 @@
 // 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.Generic;
-
-namespace Tasque
+namespace Tasque.Data
 {
-       public class TaskComparer : Comparer<ITask>
+       public interface ITaskListRepository
+               : ICollectionRepository<ITaskCore, ITaskListCore>
        {
-               public override int Compare (ITask x, ITask y)
-               {
-                       if (x == null || y == null)
-                               return 0;
-                       
-                       return (x.CompareTo (y));
-               }
+               bool CanChangeName (ITaskListCore taskList);
+               string UpdateName (ITaskListCore taskList, string name);
        }
 }
diff --git a/src/libtasque/Data/ITaskRepository.cs b/src/libtasque/Data/ITaskRepository.cs
new file mode 100644
index 0000000..a6e6838
--- /dev/null
+++ b/src/libtasque/Data/ITaskRepository.cs
@@ -0,0 +1,77 @@
+//
+// ITaskRepository.cs
+//
+// Author:
+//       Antonius Riha <antoniusriha gmail com>
+//
+// Copyright (c) 2013 Antonius Riha
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+
+namespace Tasque.Data
+{
+       public interface ITaskRepository
+               : ICollectionRepository<INoteCore, ITaskCore>,
+               ICollectionRepository<ITaskCore, ITaskCore>
+       {
+               /// <summary>
+               /// Determines whether the specified instance can have nested tasks.
+               /// HINT: If nested tasks are not supported by the backend, always
+               /// return <c>false</c>.
+               /// </summary>
+               /// <returns>
+               /// <c>true</c> if the specified instance can have nested tasks task;
+               /// otherwise, <c>false</c>.
+               /// </returns>
+               /// <param name='task'>
+               /// Task.
+               /// </param>
+               bool SupportsNestedTasks { get; }
+
+               /// <summary>
+               /// Gets a value indicating whether this task/backend supports putting
+               /// a task in the trash. This means that a task is not totally deleted
+               /// from a backend, but put into a virtual trash bin, from which it may
+               /// be restored later. HINT: If discarding/recycling is not supported
+               /// by the backend, always return <c>false</c>.
+               /// </summary>
+               /// <value>
+               /// <c>true</c> if a task can be discarded; otherwise, <c>false</c>.
+               /// </value>
+               bool SupportsDiscarding { get; }
+
+               /// <summary>
+               /// Gets the type of note support of this task/backend.
+               /// </summary>
+               /// <value>
+               /// The note support.
+               /// </value>
+               NoteSupport NoteSupport { get; }
+
+               INoteCore UpdateNote (ITaskCore task, INoteCore note);
+
+               DateTime UpdateDueDate (ITaskCore task, DateTime date);
+               string UpdateText (ITaskCore task, string text);
+               TaskPriority UpdatePriority (ITaskCore task, TaskPriority priority);
+               void Activate (ITaskCore task);
+               DateTime Complete (ITaskCore task, DateTime completionDate);
+               void Discard (ITaskCore task);
+       }
+}
diff --git a/src/libtasque/Data/TasqueObjectFactory.cs b/src/libtasque/Data/TasqueObjectFactory.cs
new file mode 100644
index 0000000..8e4812a
--- /dev/null
+++ b/src/libtasque/Data/TasqueObjectFactory.cs
@@ -0,0 +1,82 @@
+//
+// TasqueObjectFactory.cs
+//
+// Author:
+//       Antonius Riha <antoniusriha gmail com>
+//
+// Copyright (c) 2013 Antonius Riha
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using Tasque.Core.Impl;
+
+namespace Tasque.Data
+{
+       public class TasqueObjectFactory
+       {
+               public TasqueObjectFactory (ITaskListRepository taskListRepo,
+                       ITaskRepository taskRepo, INoteRepository noteRepo = null)
+               {
+                       if (taskListRepo == null)
+                               throw new ArgumentNullException ("taskListRepo");
+                       if (taskRepo == null)
+                               throw new ArgumentNullException ("taskRepo");
+                       this.taskListRepo = taskListRepo;
+                       this.taskRepo = taskRepo;
+                       this.noteRepo = noteRepo;
+               }
+
+               public INoteCore CreateNote (string id)
+               {
+                       return Note.CreateNote (id, noteRepo);
+               }
+
+               public ITaskListCore CreateTaskList (string id, string name)
+               {
+                       return TaskList.CreateTaskList (
+                               id, name, taskListRepo, taskRepo, noteRepo);
+               }
+               
+               public ITaskListCore CreateSmartTaskList (string id, string name)
+               {
+                       return TaskList.CreateSmartTaskList (id, name, taskListRepo);
+               }
+
+               public ITaskCore CreateTask (string id, string text)
+               {
+                       return Task.CreateTask (id, text, taskRepo, noteRepo);
+               }
+
+               public ITaskCore CreateCompletedTask (string id, string text,
+                                                     DateTime completionDate)
+               {
+                       return Task.CreateCompletedTask (
+                               id, text, completionDate, taskRepo, noteRepo);
+               }
+
+               public ITaskCore CreateDiscardedTask (string id, string text)
+               {
+                       return Task.CreateDiscardedTask (id, text, taskRepo, noteRepo);
+               }
+
+               ITaskListRepository taskListRepo;
+               ITaskRepository taskRepo;
+               INoteRepository noteRepo;
+       }
+}
diff --git a/src/libtasque/Data/TransactionException.cs b/src/libtasque/Data/TransactionException.cs
new file mode 100644
index 0000000..a694942
--- /dev/null
+++ b/src/libtasque/Data/TransactionException.cs
@@ -0,0 +1,67 @@
+//
+// TransactionException.cs
+//
+// Author:
+//       Antonius Riha <antoniusriha gmail com>
+//
+// Copyright (c) 2013 Antonius Riha
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using System.Runtime.Serialization;
+
+namespace Tasque.Data
+{
+       [Serializable]
+       public class TransactionException : Exception
+       {
+               /// <summary>
+               /// Initializes a new instance of the <see cref="T:TransactionException"/> class
+               /// </summary>
+               public TransactionException ()
+               {
+               }
+               
+               /// <summary>
+               /// Initializes a new instance of the <see cref="T:TransactionException"/> class
+               /// </summary>
+               /// <param name="message">A <see cref="T:System.String"/> that describes the exception. 
</param>
+               public TransactionException (string message) : base (message)
+               {
+               }
+               
+               /// <summary>
+               /// Initializes a new instance of the <see cref="T:TransactionException"/> class
+               /// </summary>
+               /// <param name="message">A <see cref="T:System.String"/> that describes the exception. 
</param>
+               /// <param name="inner">The exception that is the cause of the current exception. </param>
+               public TransactionException (string message, Exception inner) : base (message, inner)
+               {
+               }
+               
+               /// <summary>
+               /// Initializes a new instance of the <see cref="T:TransactionException"/> class
+               /// </summary>
+               /// <param name="context">The contextual information about the source or destination.</param>
+               /// <param name="info">The object that holds the serialized object data.</param>
+               protected TransactionException (SerializationInfo info, StreamingContext context) : base 
(info, context)
+               {
+               }
+       }
+}
diff --git a/src/libtasque/DateFormatterFactory.cs b/src/libtasque/DateFormatters/DateFormatterFactory.cs
similarity index 98%
rename from src/libtasque/DateFormatterFactory.cs
rename to src/libtasque/DateFormatters/DateFormatterFactory.cs
index 825b180..9b016eb 100644
--- a/src/libtasque/DateFormatterFactory.cs
+++ b/src/libtasque/DateFormatters/DateFormatterFactory.cs
@@ -26,7 +26,7 @@ using System.Reflection;
 using System.Collections.Generic;
 using Tasque.DateFormatters;
 
-namespace Tasque {
+namespace Tasque.DateFormatters {
 
        sealed class DateFormatterFactory {
 
diff --git a/src/libtasque/Extensions.cs b/src/libtasque/DateFormatters/Extensions.cs
similarity index 85%
rename from src/libtasque/Extensions.cs
rename to src/libtasque/DateFormatters/Extensions.cs
index 204f24f..716b5b8 100644
--- a/src/libtasque/Extensions.cs
+++ b/src/libtasque/DateFormatters/Extensions.cs
@@ -24,35 +24,10 @@
 using System;
 using System.Linq;
 
-namespace Tasque {
+namespace Tasque.DateFormatters {
 
        internal static class Extensions {
 
-               #region DayOfWeek Extensions
-
-               internal static uint ToUint (this DayOfWeek dayOfWeek)
-               {
-                       switch (dayOfWeek) {
-                       case DayOfWeek.Sunday:
-                               return 0;
-                       case DayOfWeek.Monday:
-                               return 1;
-                       case DayOfWeek.Tuesday:
-                               return 2;
-                       case DayOfWeek.Wednesday:
-                               return 3;
-                       case DayOfWeek.Thursday:
-                               return 4;
-                       case DayOfWeek.Friday:
-                               return 5;
-                       case DayOfWeek.Saturday:
-                       default:
-                               return 6;
-                       }
-               }
-
-               #endregion
-
                #region String Extensions
 
                internal static DayOfWeek ToDayOfWeek (this string str)
diff --git a/src/libtasque/RegularExpressionFormatter.cs 
b/src/libtasque/DateFormatters/RegularExpressionFormatter.cs
similarity index 98%
rename from src/libtasque/RegularExpressionFormatter.cs
rename to src/libtasque/DateFormatters/RegularExpressionFormatter.cs
index 5b01387..7c1c53c 100644
--- a/src/libtasque/RegularExpressionFormatter.cs
+++ b/src/libtasque/DateFormatters/RegularExpressionFormatter.cs
@@ -25,7 +25,7 @@ using System;
 using System.Collections.Generic;
 using Tasque.DateFormatters;
 
-namespace Tasque {
+namespace Tasque.DateFormatters {
 
        // Used to keep a relation of Regular Expression and the
        // formatters used to get the date.
diff --git a/src/libtasque/TaskParser.cs b/src/libtasque/DateFormatters/TaskParser.cs
similarity index 99%
rename from src/libtasque/TaskParser.cs
rename to src/libtasque/DateFormatters/TaskParser.cs
index f1e230b..b0059c9 100644
--- a/src/libtasque/TaskParser.cs
+++ b/src/libtasque/DateFormatters/TaskParser.cs
@@ -28,7 +28,7 @@ using System.Linq;
 using System.Text.RegularExpressions;
 using Tasque.DateFormatters;
 
-namespace Tasque {
+namespace Tasque.DateFormatters {
        
        // TODO: Support for time parsing
 
diff --git a/src/libtasque/TranslatableToken.cs b/src/libtasque/DateFormatters/TranslatableToken.cs
similarity index 97%
rename from src/libtasque/TranslatableToken.cs
rename to src/libtasque/DateFormatters/TranslatableToken.cs
index fe4353d..4372d26 100644
--- a/src/libtasque/TranslatableToken.cs
+++ b/src/libtasque/DateFormatters/TranslatableToken.cs
@@ -23,7 +23,7 @@
 
 using System;
 
-namespace Tasque {
+namespace Tasque.DateFormatters {
 
        class TranslatableToken {
 
diff --git a/src/libtasque/DateFormatters/WeekdayFormatter.cs 
b/src/libtasque/DateFormatters/WeekdayFormatter.cs
index 4c78c68..4cf2378 100644
--- a/src/libtasque/DateFormatters/WeekdayFormatter.cs
+++ b/src/libtasque/DateFormatters/WeekdayFormatter.cs
@@ -35,9 +35,9 @@ namespace Tasque.DateFormatters {
                                return DateTime.MinValue;
 
                        DateTime todayDateTime = DateTime.Now;
-                       uint today = todayDateTime.DayOfWeek.ToUint ();
-                       uint future = weekDay.ToDayOfWeek ().ToUint ();
-                       if (future > today) 
+                       var today = (int)todayDateTime.DayOfWeek;
+                       var future = (int)weekDay.ToDayOfWeek ();
+                       if (future > today)
                                return DateTime.Now.AddDays (future - today);
                        else if (today > future)
                                return DateTime.Now.AddDays (7 - (today - future));
diff --git a/src/libtasque/TaskComparer.cs b/src/libtasque/IContainee.cs
similarity index 83%
copy from src/libtasque/TaskComparer.cs
copy to src/libtasque/IContainee.cs
index 1285fe1..6351b9c 100644
--- a/src/libtasque/TaskComparer.cs
+++ b/src/libtasque/IContainee.cs
@@ -1,10 +1,10 @@
 //
-// TaskComparer.cs
+// IContainee.cs
 //
 // Author:
 //       Antonius Riha <antoniusriha gmail com>
 //
-// Copyright (c) 2012 Antonius Riha
+// Copyright (c) 2013 Antonius Riha
 //
 // Permission is hereby granted, free of charge, to any person obtaining a copy
 // of this software and associated documentation files (the "Software"), to deal
@@ -27,14 +27,9 @@ using System.Collections.Generic;
 
 namespace Tasque
 {
-       public class TaskComparer : Comparer<ITask>
+       public interface IContainee<out TContainer>
+               where TContainer : ITasqueCore
        {
-               public override int Compare (ITask x, ITask y)
-               {
-                       if (x == null || y == null)
-                               return 0;
-                       
-                       return (x.CompareTo (y));
-               }
+               IEnumerable<TContainer> Containers { get; }
        }
 }
diff --git a/src/libtasque/IBackendPreferences.cs b/src/libtasque/INoteCore.cs
similarity index 84%
copy from src/libtasque/IBackendPreferences.cs
copy to src/libtasque/INoteCore.cs
index 1f1a236..e44d4d6 100644
--- a/src/libtasque/IBackendPreferences.cs
+++ b/src/libtasque/INoteCore.cs
@@ -1,21 +1,21 @@
-// 
-// IBackendPreferences.cs
-//  
+//
+// INoteCore.cs
+//
 // Author:
 //       Antonius Riha <antoniusriha gmail com>
-// 
-// Copyright (c) 2012 Antonius Riha
-// 
+//
+// Copyright (c) 2013 Antonius Riha
+//
 // Permission is hereby granted, free of charge, to any person obtaining a copy
 // of this software and associated documentation files (the "Software"), to deal
 // in the Software without restriction, including without limitation the rights
 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 // copies of the Software, and to permit persons to whom the Software is
 // furnished to do so, subject to the following conditions:
-// 
+//
 // The above copyright notice and this permission notice shall be included in
 // all copies or substantial portions of the Software.
-// 
+//
 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -23,10 +23,11 @@
 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 // THE SOFTWARE.
-
-namespace Tasque.Backends
+namespace Tasque
 {
-       public interface IBackendPreferences
+       public interface INoteCore : ITasqueCore, IContainee<ITaskCore>
        {
+               string Title { get; set; }
+               string Text { get; set; }
        }
 }
diff --git a/src/libtasque/CategoryComparer.cs b/src/libtasque/ITaskCore.cs
similarity index 76%
copy from src/libtasque/CategoryComparer.cs
copy to src/libtasque/ITaskCore.cs
index b81fcfa..a398526 100644
--- a/src/libtasque/CategoryComparer.cs
+++ b/src/libtasque/ITaskCore.cs
@@ -1,10 +1,10 @@
 //
-// CategoryComparer.cs
+// ITaskCore.cs
 //
 // Author:
 //       Antonius Riha <antoniusriha gmail com>
 //
-// Copyright (c) 2012 Antonius Riha
+// Copyright (c) 2013 Antonius Riha
 //
 // Permission is hereby granted, free of charge, to any person obtaining a copy
 // of this software and associated documentation files (the "Software"), to deal
@@ -23,23 +23,19 @@
 // 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;
 
 namespace Tasque
 {
-       public class CategoryComparer : Comparer<ICategory>
+       public interface ITaskCore : ITasqueCore,
+               IContainee<ITaskListCore>, IContainee<ITaskCore>
        {
-               public override int Compare (ICategory x, ICategory y)
-               {
-                       if (x == null || y == null)
-                               return 0;
-                       
-                       if (x is AllCategory)
-                               return -1;
-                       else if (y is AllCategory)
-                               return 1;
-                       
-                       return (x.Name.CompareTo (y.Name));
-               }
+               string Text { get; set; }
+               DateTime DueDate { get; set; }
+               TaskPriority Priority { get; set; }
+
+               IEnumerable<ITaskListCore> TaskListContainers { get; }
+               IEnumerable<ITaskCore> TaskContainers { get; }
        }
 }
diff --git a/src/libtasque/IBackendPreferences.cs b/src/libtasque/ITaskListCore.cs
similarity index 87%
copy from src/libtasque/IBackendPreferences.cs
copy to src/libtasque/ITaskListCore.cs
index 1f1a236..c01f226 100644
--- a/src/libtasque/IBackendPreferences.cs
+++ b/src/libtasque/ITaskListCore.cs
@@ -1,21 +1,21 @@
-// 
-// IBackendPreferences.cs
-//  
+//
+// ITaskListCore.cs
+//
 // Author:
 //       Antonius Riha <antoniusriha gmail com>
-// 
-// Copyright (c) 2012 Antonius Riha
-// 
+//
+// Copyright (c) 2013 Antonius Riha
+//
 // Permission is hereby granted, free of charge, to any person obtaining a copy
 // of this software and associated documentation files (the "Software"), to deal
 // in the Software without restriction, including without limitation the rights
 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 // copies of the Software, and to permit persons to whom the Software is
 // furnished to do so, subject to the following conditions:
-// 
+//
 // The above copyright notice and this permission notice shall be included in
 // all copies or substantial portions of the Software.
-// 
+//
 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -23,10 +23,10 @@
 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 // THE SOFTWARE.
-
-namespace Tasque.Backends
+namespace Tasque
 {
-       public interface IBackendPreferences
+       public interface ITaskListCore : ITasqueCore
        {
+               string Name { get; set; }
        }
 }
diff --git a/src/libtasque/IBackendPreferences.cs b/src/libtasque/ITasqueCore.cs
similarity index 88%
rename from src/libtasque/IBackendPreferences.cs
rename to src/libtasque/ITasqueCore.cs
index 1f1a236..0a26b8a 100644
--- a/src/libtasque/IBackendPreferences.cs
+++ b/src/libtasque/ITasqueCore.cs
@@ -1,21 +1,21 @@
-// 
-// IBackendPreferences.cs
-//  
+//
+// ITasqueCore.cs
+//
 // Author:
 //       Antonius Riha <antoniusriha gmail com>
-// 
-// Copyright (c) 2012 Antonius Riha
-// 
+//
+// Copyright (c) 2013 Antonius Riha
+//
 // Permission is hereby granted, free of charge, to any person obtaining a copy
 // of this software and associated documentation files (the "Software"), to deal
 // in the Software without restriction, including without limitation the rights
 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 // copies of the Software, and to permit persons to whom the Software is
 // furnished to do so, subject to the following conditions:
-// 
+//
 // The above copyright notice and this permission notice shall be included in
 // all copies or substantial portions of the Software.
-// 
+//
 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -23,10 +23,10 @@
 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 // THE SOFTWARE.
-
-namespace Tasque.Backends
+namespace Tasque
 {
-       public interface IBackendPreferences
+       public interface ITasqueCore
        {
+               string Id { get; }
        }
 }
diff --git a/src/libtasque/PreferencesKeys.cs b/src/libtasque/PreferencesKeys.cs
index 4b12682..c0ed2f4 100644
--- a/src/libtasque/PreferencesKeys.cs
+++ b/src/libtasque/PreferencesKeys.cs
@@ -31,23 +31,23 @@ namespace Tasque
                public const string AuthTokenKey = "AuthToken";
                public const string CurrentBackend = "CurrentBackend";
                public const string InactivateTimeoutKey = "InactivateTimeout";
-               public const string SelectedCategoryKey = "SelectedCategory";
+               public const string SelectedTaskListKey = "SelectedTaskList";
                public const string ParseDateEnabledKey = "ParseDateEnabled";
                public const string TodayTaskTextColor = "TodayTaskTextColor";
                public const string OverdueTaskTextColor = "OverdueTaskTextColor";
                
                /// <summary>
-               /// A list of category names to show in the TaskWindow when the "All"
-               /// category is selected.
+               /// A list of taskList names to show in the TaskWindow when the "All"
+               /// taskList is selected.
                /// </summary>
-               public const string HideInAllCategory = "HideInAllCategory";
+               public const string HideInAllTaskList = "HideInAllTaskList";
                public const string ShowCompletedTasksKey = "ShowCompletedTasks";
                public const string UserNameKey = "UserName";
                public const string UserIdKey = "UserID";
                
                /// <summary>
                /// This setting allows a user to specify how many completed tasks to
-               /// show in the Completed Tasks Category.  The setting should be one of:
+               /// show in the Completed Tasks TaskList.  The setting should be one of:
                /// "Yesterday", "Last7Days", "LastMonth", "LastYear", or "All".
                /// </summary>
                public const string CompletedTasksRange = "CompletedTasksRange";
diff --git a/src/libtasque/Properties/AssemblyInfo.cs b/src/libtasque/Properties/AssemblyInfo.cs
index 678bf49..ef25859 100644
--- a/src/libtasque/Properties/AssemblyInfo.cs
+++ b/src/libtasque/Properties/AssemblyInfo.cs
@@ -24,6 +24,8 @@
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 // THE SOFTWARE.
 using System.Reflection;
+using Mono.Addins;
 
 [assembly: AssemblyTitle("libtasque")]
 [assembly: AssemblyDescription("Platform-independent Tasque library")]
+[assembly: AddinRoot ("libtasque", "0.2.0")]
diff --git a/src/libtasque/TaskPriority.cs b/src/libtasque/TaskPriority.cs
index 900466d..d6ad2cc 100644
--- a/src/libtasque/TaskPriority.cs
+++ b/src/libtasque/TaskPriority.cs
@@ -1,13 +1,38 @@
+//
+// TaskPriority.cs
+//
+// Original header:
 // TaskPriority.cs created with MonoDevelop
-// User: boyd at 12:29 PM 2/11/2008
-
-using System;
-
+// User: boyd at 12:29 PM 2/11/2008
+//
+// Authors:
+//       Unknown author
+//       Antonius Riha <antoniusriha gmail com>
+//
+// Copyright (c) 2013 Antonius Riha
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
 namespace Tasque
 {
        public enum TaskPriority
        {
-               None = 0,
+               None,
                Low,
                Medium,
                High
diff --git a/src/libtasque/Utils/AllList.cs b/src/libtasque/Utils/AllList.cs
new file mode 100644
index 0000000..99fa015
--- /dev/null
+++ b/src/libtasque/Utils/AllList.cs
@@ -0,0 +1,235 @@
+//
+// AllList.cs
+//
+// Original header:
+// AllCategory.cs created with MonoDevelop
+// User: boyd at 3:45 PM 2/12/2008
+//
+// Authors:
+//       Unknown author
+//       Antonius Riha <antoniusriha gmail com>
+//
+// Copyright (c) 2013 Antonius Riha
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Collections.Specialized;
+using System.ComponentModel;
+using System.Linq;
+using Mono.Unix;
+using Tasque.Core;
+
+namespace Tasque.Utils
+{
+       public sealed class AllList : ITaskList
+       {
+               internal static void SetBackendManager (BackendManager manager)
+               {
+                       if (manager == null)
+                               throw new ArgumentNullException ("manager");
+                       AllList.manager = manager;
+               }
+
+               static BackendManager manager;
+
+               public AllList (IPreferences preferences)
+               {
+                       if (manager == null)
+                               throw new InvalidOperationException ("Internal error. " +
+                                       "BackendManager must be set beforehand.");
+                       if (preferences == null)
+                               throw new ArgumentNullException ("preferences");
+                       backendManager = manager;
+
+                       tasks = new ObservableCollection<ITask> ();
+                       
+                       taskListsToHide = preferences.GetStringList (
+                               PreferencesKeys.HideInAllTaskList);
+                       preferences.SettingChanged += (prefs, settingKey) => {
+                               if (settingKey != PreferencesKeys.HideInAllTaskList)
+                                       return;
+                               taskListsToHide = prefs.GetStringList (
+                                       PreferencesKeys.HideInAllTaskList);
+                               UpdateList ();
+                       };
+                       
+                       observedLists = new List<ITaskList> ();
+                       UpdateList ();
+                       
+                       ((INotifyCollectionChanged)manager.TaskLists)
+                               .CollectionChanged += delegate { UpdateList (); };
+               }
+
+               public bool CanChangeName { get { return false; } }
+
+               public string Name {
+                       get { return Catalog.GetString ("All"); }
+                       set {
+                               throw new InvalidOperationException (
+                                       "The name of this list cannot be changed.");
+                       }
+               }
+
+               public TaskListType ListType { get { return TaskListType.Smart; } }
+
+               public int Count { get { return tasks.Count; } }
+
+               public bool IsReadOnly { get { return true; } }
+
+               public bool Contains (ITask item)
+               {
+                       return tasks.Contains (item);
+               }
+
+               public void CopyTo (ITask [] array, int arrayIndex)
+               {
+                       tasks.CopyTo (array, arrayIndex);
+               }
+
+               public IEnumerator<ITask> GetEnumerator ()
+               {
+                       return tasks.GetEnumerator ();
+               }
+
+               public event NotifyCollectionChangedEventHandler CollectionChanged {
+                       add { tasks.CollectionChanged += value; }
+                       remove { tasks.CollectionChanged -= value; }
+               }
+
+               #region Explicit content
+
+               string ITasqueCore.Id { get { return null; } }
+
+               bool ITaskList.SupportsSharingTasksWithOtherTaskLists {
+                       get { return true; }
+               }
+
+               ITask ITaskList.CreateTask (string text)
+               {
+                       return null;
+               }
+
+               void ITasqueObject.Refresh () {}
+
+               void ICollection<ITask>.Add (ITask item)
+               {
+                       ThrowReadOnly ();
+               }
+
+               void ICollection<ITask>.Clear ()
+               {
+                       ThrowReadOnly ();
+               }
+
+               bool ICollection<ITask>.Remove (ITask item)
+               {
+                       return false;
+               }
+
+               IEnumerator IEnumerable.GetEnumerator ()
+               {
+                       return GetEnumerator ();
+               }
+
+               event PropertyChangedEventHandler
+                       INotifyPropertyChanged.PropertyChanged {
+                       add {} remove {}
+               }
+
+               event PropertyChangingEventHandler
+                       INotifyPropertyChanging.PropertyChanging {
+                       add {} remove {}
+               }
+
+               #endregion
+
+               void UpdateList ()
+               {
+                       // clear all
+                       foreach (var list in observedLists)
+                               list.CollectionChanged -= HandleTaskListChanged;
+                       observedLists.Clear ();
+                       tasks.Clear ();
+
+                       // add all
+                       foreach (var list in backendManager.TaskLists) {
+                               if (list.ListType == TaskListType.Smart
+                                   || taskListsToHide.Contains (list.Name))
+                                       continue;
+
+                               foreach (var task in list)
+                                       AddTask (task);
+
+                               // register list
+                               observedLists.Add (list);
+                               list.CollectionChanged += HandleTaskListChanged;
+                       }
+               }
+
+               void HandleTaskListChanged (object sender, NotifyCollectionChangedEventArgs e)
+               {
+                       switch (e.Action) {
+                       case NotifyCollectionChangedAction.Add:
+                               AddTask (e.NewItems [0] as ITask);
+                               break;
+                       case NotifyCollectionChangedAction.Remove:
+                               RemoveTask (e.OldItems [0] as ITask);
+                               break;
+                       case NotifyCollectionChangedAction.Replace:
+                               RemoveTask (e.OldItems [0] as ITask);
+                               AddTask (e.NewItems [0] as ITask);
+                               break;
+                       case NotifyCollectionChangedAction.Reset:
+                               UpdateList ();
+                               break;
+                       }
+               }
+
+               void AddTask (ITask task)
+               {
+                       if (!tasks.Contains (task))
+                               tasks.Add (task);
+               }
+
+               void RemoveTask (ITask task)
+               {
+                       // if the old task exists exactly once, remove it
+                       if (observedLists.Count (l => l.Contains (task)) == 1)
+                               tasks.Remove (task);
+               }
+
+               void ThrowReadOnly ()
+               {
+                       throw new InvalidOperationException (
+                               "This collection is read-only.");
+               }
+
+               // A "set" of taskLists specified by the user to show when the "All"
+               // taskList is selected in the TaskWindow. If the list is empty, tasks
+               // from all taskLists will be shown. Otherwise, only tasks from the
+               // specified lists will be shown.
+               List<string> taskListsToHide;
+               List<ITaskList> observedLists;
+               ObservableCollection<ITask> tasks;
+               BackendManager backendManager;
+       }
+}
diff --git a/src/libtasque/CompletedTaskGroupModel.cs b/src/libtasque/Utils/CompletedTaskGroupModel.cs
similarity index 97%
rename from src/libtasque/CompletedTaskGroupModel.cs
rename to src/libtasque/Utils/CompletedTaskGroupModel.cs
index 1bc3afa..e3ce1fb 100644
--- a/src/libtasque/CompletedTaskGroupModel.cs
+++ b/src/libtasque/Utils/CompletedTaskGroupModel.cs
@@ -1,8 +1,9 @@
 
 using System;
 using System.Collections.Generic;
+using Tasque.Core;
 
-namespace Tasque
+namespace Tasque.Utils
 {
        public class CompletedTaskGroupModel : TaskGroupModel
        {
@@ -30,7 +31,7 @@ namespace Tasque
                        // Don't show any task here if showCompletedTasks is false
                        if (!showCompletedTasks)
                                return false;
-                       
+
                        if (task == null || task.State != TaskState.Completed)
                                return false;
                        
diff --git a/src/libtasque/Preferences.cs b/src/libtasque/Utils/Preferences.cs
similarity index 99%
rename from src/libtasque/Preferences.cs
rename to src/libtasque/Utils/Preferences.cs
index 3fbd806..29e440a 100644
--- a/src/libtasque/Preferences.cs
+++ b/src/libtasque/Utils/Preferences.cs
@@ -33,7 +33,7 @@ using System.Collections.Generic;
 using System.Xml;
 using System.IO;
 
-namespace Tasque 
+namespace Tasque.Utils
 {
        // <summary>
        // Class used to store Tasque preferences
diff --git a/src/libtasque/Utils/TaskComparer.cs b/src/libtasque/Utils/TaskComparer.cs
new file mode 100644
index 0000000..28158b3
--- /dev/null
+++ b/src/libtasque/Utils/TaskComparer.cs
@@ -0,0 +1,98 @@
+//
+// TaskComparer.cs
+//
+// Author:
+//       Antonius Riha <antoniusriha gmail com>
+//
+// Copyright (c) 2012 Antonius Riha
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using System.Collections.Generic;
+using Tasque.Core;
+
+namespace Tasque.Utils
+{
+       public class TaskComparer : Comparer<ITask>
+       {
+               /// <summary>
+               /// This is used for sorting tasks in the TaskWindow and should compare
+               /// based on due date.
+               /// </summary>
+               /// <returns>
+               /// whether the task has lower, equal or higher sort order.
+               /// </returns>
+               public override int Compare (ITask x, ITask y)
+               {
+                       if (x == null || y == null)
+                               return 0;
+
+                       bool isSameDate = true;
+                       if (x.DueDate.Year != y.DueDate.Year
+                           || x.DueDate.DayOfYear != y.DueDate.DayOfYear)
+                               isSameDate = false;
+                       
+                       if (!isSameDate) {
+                               if (x.DueDate == DateTime.MinValue) {
+                                       // No due date set on this task. Since we already tested to see
+                                       // if the dates were the same above, we know that the passed-in
+                                       // task has a due date set and it should be "higher" in a sort.
+                                       return 1;
+                               } else if (y.DueDate == DateTime.MinValue) {
+                                       // This task has a due date and should be "first" in sort order.
+                                       return -1;
+                               }
+                               
+                               int result = x.DueDate.CompareTo (y.DueDate);
+                               
+                               if (result != 0)
+                                       return result;
+                       }
+                       
+                       // The due dates match, so now sort based on priority and name
+                       return CompareByPriorityAndName (x, y);
+               }
+
+               protected int CompareByPriorityAndName (ITask x, ITask y)
+               {
+                       // The due dates match, so now sort based on priority
+                       if (x.Priority != y.Priority) {
+                               switch (x.Priority) {
+                               case TaskPriority.High:
+                                       return -1;
+                               case TaskPriority.Medium:
+                                       if (y.Priority == TaskPriority.High)
+                                               return 1;
+                                       else
+                                               return -1;
+                               case TaskPriority.Low:
+                                       if (y.Priority == TaskPriority.None)
+                                               return -1;
+                                       else
+                                               return 1;
+                               case TaskPriority.None:
+                                       return 1;
+                               }
+                       }
+                       
+                       // Due dates and priorities match, now sort by text
+                       return x.Text.CompareTo (y.Text);
+               }
+       }
+}
diff --git a/src/libtasque/Utils/TaskCompletionDateComparer.cs 
b/src/libtasque/Utils/TaskCompletionDateComparer.cs
new file mode 100644
index 0000000..04b7942
--- /dev/null
+++ b/src/libtasque/Utils/TaskCompletionDateComparer.cs
@@ -0,0 +1,70 @@
+//
+// TaskCompletionDateComparer.cs
+//
+// Author:
+//       Antonius Riha <antoniusriha gmail com>
+//
+// Copyright (c) 2013 Antonius Riha
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using Tasque.Core;
+
+namespace Tasque.Utils
+{
+       public class TaskCompletionDateComparer : TaskComparer
+       {
+               /// <summary>
+               /// This is the same as CompareTo above but should use completion date
+               /// instead of due date.  This is used to sort items in the
+               /// CompletedTaskGroup.
+               /// </summary>
+               /// <returns>
+               /// whether the task has lower, equal or higher sort order.
+               /// </returns>
+               public override int Compare (ITask x, ITask y)
+               {
+                       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 CompareByPriorityAndName (x, y);
+               }
+       }
+}
diff --git a/src/libtasque/TaskGroupModel.cs b/src/libtasque/Utils/TaskGroupModel.cs
similarity index 75%
rename from src/libtasque/TaskGroupModel.cs
rename to src/libtasque/Utils/TaskGroupModel.cs
index 66f040c..3d25fc1 100644
--- a/src/libtasque/TaskGroupModel.cs
+++ b/src/libtasque/Utils/TaskGroupModel.cs
@@ -5,8 +5,10 @@ using System.Collections.Generic;
 using System.Collections.Specialized;
 using System.ComponentModel;
 using System.Linq;
+using Tasque.Core;
+using System.Collections.ObjectModel;
 
-namespace Tasque
+namespace Tasque.Utils
 {
        /// <summary>
        /// Task group model. Filters tasks.
@@ -203,11 +205,11 @@ namespace Tasque
                /// </summary>
                protected virtual bool FilterTasks (ITask task)
                {
-                       if (task == null || task.State == TaskState.Deleted)
+                       if (task == null || task.State == TaskState.Discarded)
                                return false;
                        
                        // Do something special when task.DueDate == DateTime.MinValue since
-                       // these tasks should always be in the very last category.
+                       // these tasks should always be in the very last taskList.
                        if (task.DueDate == DateTime.MinValue) {
                                if (timeRangeEnd == DateTime.MaxValue) {
                                        if (!ShowCompletedTask (task))
@@ -268,28 +270,34 @@ namespace Tasque
                        {
                                OriginalTaskRef = originalTask;
                                Id = originalTask.Id;
-                               Name = originalTask.Name;
+                               Text = originalTask.Text;
                                DueDate = originalTask.DueDate;
                                CompletionDate = originalTask.CompletionDate;
                                IsComplete = originalTask.IsComplete;
                                Priority = originalTask.Priority;
                                HasNotes = originalTask.HasNotes;
                                NoteSupport = originalTask.NoteSupport;
+                               SupportsSharingNotesWithOtherTasks =
+                                       originalTask.SupportsSharingNotesWithOtherTasks;
                                State = originalTask.State;
-                               Category = originalTask.Category;
+                               SupportsNestedTasks = originalTask.SupportsNestedTasks;
+                               SupportsSharingNestedTasksWithOtherTasks =
+                                       originalTask.SupportsSharingNestedTasksWithOtherTasks;
+                               HasNestedTasks = originalTask.HasNestedTasks;
+                               SupportsDiscarding = originalTask.SupportsDiscarding;
                        }
-                       
+
                        public int OriginalIndex { get; private set; }
                        
                        public ITask OriginalTaskRef { get; private set; }
                        
                        public string Id { get; private set; }
-                       
-                       public string Name { get; set; }
+
+                       public string Text { get; set; }
                        
                        public DateTime DueDate { get; set; }
                        
-                       public DateTime CompletionDate { get; set; }
+                       public DateTime CompletionDate { get; private set; }
                        
                        public bool IsComplete { get; private set; }
                        
@@ -298,72 +306,88 @@ namespace Tasque
                        public bool HasNotes { get; private set; }
                        
                        public NoteSupport NoteSupport { get; private set; }
+
+                       public bool SupportsSharingNotesWithOtherTasks { get; private set; }
                        
                        public TaskState State { get; private set; }
+
+                       public INote Note { get; set; }
+
+                       public ObservableCollection<INote> Notes { get; private set; }
                        
-                       public ICategory Category { get; set; }
-                       
-                       #region Explicit content
-                       List<INote> ITask.Notes {
-                               get { throw new NotSupportedException (); }
+                       public bool SupportsNestedTasks { get; private set; }
+
+                       public bool SupportsSharingNestedTasksWithOtherTasks { get; private set; }
+
+                       public bool HasNestedTasks { get; private set; }
+
+                       public ObservableCollection<ITask> NestedTasks {
+                               get; private set;
                        }
                        
-                       void ITask.Activate ()
-                       {
-                               throw new NotSupportedException ();
-                       }
+                       public bool SupportsDiscarding { get; private set; }
                        
-                       void ITask.Complete ()
-                       {
-                               throw new NotSupportedException ();
-                       }
+                       public IEnumerable<ITask> TaskContainers { get; private set; }
                        
-                       void ITask.Delete ()
-                       {
-                               throw new NotSupportedException ();
+                       public IEnumerable<ITaskList> TaskListContainers {
+                               get; private set;
                        }
-                       
-                       INote ITask.CreateNote (string text)
+
+                       IEnumerable<ITaskCore> IContainee<ITaskCore>.Containers {
+                               get { return TaskContainers; }
+                       }
+
+                       IEnumerable<ITaskListCore> IContainee<ITaskListCore>.Containers {
+                               get { return TaskListContainers; }
+                       }
+
+                       IEnumerable<ITaskCore> ITaskCore.TaskContainers {
+                               get { return TaskContainers; }
+                       }
+
+                       IEnumerable<ITaskListCore> ITaskCore.TaskListContainers {
+                               get { return TaskListContainers; }
+                       }
+
+                       public void Activate ()
                        {
-                               throw new NotSupportedException ();
+                               throw new NotImplementedException ();
                        }
                        
-                       void ITask.DeleteNote (INote note)
+                       public void Complete ()
                        {
-                               throw new NotSupportedException ();
+                               throw new NotImplementedException ();
                        }
                        
-                       void ITask.SaveNote (INote note)
+                       public void Discard ()
                        {
-                               throw new NotSupportedException ();
+                               throw new NotImplementedException ();
                        }
                        
-                       int ITask.CompareTo (ITask task)
+                       public INote CreateNote ()
                        {
-                               throw new NotSupportedException ();
+                               throw new NotImplementedException ();
                        }
                        
-                       int ITask.CompareToByCompletionDate (ITask task)
+                       public INote CreateNote (string text)
                        {
-                               throw new NotSupportedException ();
+                               throw new NotImplementedException ();
                        }
                        
-                       event PropertyChangedEventHandler INotifyPropertyChanged.PropertyChanged {
-                               add {
-                                       throw new NotSupportedException ();
-                               } remove {
-                                       throw new NotSupportedException ();
-                               }
+                       public ITask CreateNestedTask (string text)
+                       {
+                               throw new NotImplementedException ();
                        }
                        
-                       event PropertyChangingEventHandler INotifyPropertyChanging.PropertyChanging {
-                               add {
-                                       throw new NotSupportedException ();
-                               } remove {
-                                       throw new NotSupportedException ();
-                               }
+                       public void Refresh ()
+                       {
+                               throw new NotImplementedException ();
                        }
-                       #endregion
+
+                       public event EventHandler Completing, Completed,
+                               Activating, Activated, Discarding, Discarded;
+                       public event PropertyChangedEventHandler PropertyChanged;
+                       public event PropertyChangingEventHandler PropertyChanging;
                }
        }
 }
diff --git a/src/libtasque/CategoryComparer.cs b/src/libtasque/Utils/TaskListComparer.cs
similarity index 85%
copy from src/libtasque/CategoryComparer.cs
copy to src/libtasque/Utils/TaskListComparer.cs
index b81fcfa..ae10d77 100644
--- a/src/libtasque/CategoryComparer.cs
+++ b/src/libtasque/Utils/TaskListComparer.cs
@@ -1,5 +1,5 @@
 //
-// CategoryComparer.cs
+// TaskListComparer.cs
 //
 // Author:
 //       Antonius Riha <antoniusriha gmail com>
@@ -24,21 +24,22 @@
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 // THE SOFTWARE.
 using System.Collections.Generic;
+using Tasque.Core;
 
-namespace Tasque
+namespace Tasque.Utils
 {
-       public class CategoryComparer : Comparer<ICategory>
+       public class TaskListComparer : Comparer<ITaskList>
        {
-               public override int Compare (ICategory x, ICategory y)
+               public override int Compare (ITaskList x, ITaskList y)
                {
                        if (x == null || y == null)
                                return 0;
                        
-                       if (x is AllCategory)
+                       if (x is AllList)
                                return -1;
-                       else if (y is AllCategory)
+                       else if (y is AllList)
                                return 1;
-                       
+
                        return (x.Name.CompareTo (y.Name));
                }
        }
diff --git a/src/libtasque/libtasque.csproj b/src/libtasque/libtasque.csproj
index b071a42..61f93bb 100644
--- a/src/libtasque/libtasque.csproj
+++ b/src/libtasque/libtasque.csproj
@@ -12,7 +12,7 @@
     <AssemblyName>libtasque</AssemblyName>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
-    <ReleaseVersion>0.1.13</ReleaseVersion>
+    <ReleaseVersion>0.2.0</ReleaseVersion>
     <PackageName>tasque</PackageName>
     <TopBuildDir>..\..</TopBuildDir>
   </PropertyGroup>
@@ -34,16 +34,12 @@
     <Reference Include="System.Core" />
     <Reference Include="Mono.Posix" />
     <Reference Include="System.Xml" />
+    <Reference Include="Mono.Addins, Version=0.6.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756">
+      <Private>False</Private>
+      <Package>mono-addins</Package>
+    </Reference>
   </ItemGroup>
   <ItemGroup>
-    <Compile Include="IBackend.cs" />
-    <Compile Include="ICategory.cs" />
-    <Compile Include="INote.cs" />
-    <Compile Include="ITask.cs" />
-    <Compile Include="TaskPriority.cs" />
-    <Compile Include="TaskState.cs" />
-    <Compile Include="TaskParser.cs" />
-    <Compile Include="DateFormatterFactory.cs" />
     <Compile Include="DateFormatters\IDateFormatter.cs" />
     <Compile Include="DateFormatters\WeekdayFormatter.cs" />
     <Compile Include="DateFormatters\OrdinalFormatter.cs" />
@@ -54,37 +50,79 @@
     <Compile Include="DateFormatters\DateFormatter.cs" />
     <Compile Include="DateFormatters\MonthFormatter.cs" />
     <Compile Include="DateFormatters\TodayTomorrowFormatter.cs" />
-    <Compile Include="RegularExpressionFormatter.cs" />
-    <Compile Include="TranslatableToken.cs" />
-    <Compile Include="Extensions.cs" />
     <Compile Include="DateFormatters\DayFormatter.cs" />
     <Compile Include="DateFormatters\DateSeparatedFormatter.cs" />
-    <Compile Include="INativeApplication.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="..\..\build\CommonAssemblyInfo.cs">
       <Link>Properties\CommonAssemblyInfo.cs</Link>
     </Compile>
-    <Compile Include="IBackendPreferences.cs" />
-    <Compile Include="NativeApplication.cs" />
     <Compile Include="Logger.cs" />
-    <Compile Include="..\Options.cs">
-      <Link>Options.cs</Link>
-    </Compile>
-    <Compile Include="Preferences.cs" />
-    <Compile Include="TaskGroupModel.cs" />
-    <Compile Include="TaskGroupModelFactory.cs" />
-    <Compile Include="CompletedTaskGroupModel.cs" />
-    <Compile Include="CategoryComparer.cs" />
-    <Compile Include="TaskComparer.cs" />
-    <Compile Include="AllCategory.cs" />
-    <Compile Include="IPreferences.cs" />
     <Compile Include="PreferencesKeys.cs" />
+    <Compile Include="DateFormatters\TaskParser.cs" />
+    <Compile Include="DateFormatters\Extensions.cs" />
+    <Compile Include="DateFormatters\TranslatableToken.cs" />
+    <Compile Include="DateFormatters\RegularExpressionFormatter.cs" />
+    <Compile Include="DateFormatters\DateFormatterFactory.cs" />
+    <Compile Include="Data\BackendExtensionAttribute.cs" />
+    <Compile Include="Data\BackendInitializationException.cs" />
+    <Compile Include="Data\IBackend2.cs" />
+    <Compile Include="Data\IBackendPreferences.cs" />
+    <Compile Include="Data\INoteRepository.cs" />
+    <Compile Include="Data\IRepository.cs" />
+    <Compile Include="Data\ITaskListRepository.cs" />
+    <Compile Include="Data\ITaskRepository.cs" />
+    <Compile Include="Data\IRepositoryProvider.cs" />
+    <Compile Include="Data\TransactionException.cs" />
+    <Compile Include="IPreferences.cs" />
+    <Compile Include="Data\ICollectionRepository.cs" />
+    <Compile Include="Core\TaskState.cs" />
+    <Compile Include="Data\TasqueObjectFactory.cs" />
+    <Compile Include="Core\INote.cs" />
+    <Compile Include="Core\ITasqueObject.cs" />
+    <Compile Include="Core\Impl\Note.cs" />
+    <Compile Include="Core\Impl\Task.cs" />
+    <Compile Include="Core\Impl\TaskList.cs" />
+    <Compile Include="Core\ITaskList.cs" />
+    <Compile Include="Core\ITask.cs" />
+    <Compile Include="Core\Impl\TasqueObject.cs" />
+    <Compile Include="Core\Impl\TasqueObjectCollection.cs" />
+    <Compile Include="Core\Impl\IBackendDetachable.cs" />
+    <Compile Include="Core\Impl\IInternalContainee.cs" />
+    <Compile Include="Data\Extensions.cs" />
+    <Compile Include="Core\Impl\IIdEditable.cs" />
+    <Compile Include="Core\Impl\Extensions.cs" />
+    <Compile Include="Core\Impl\INotifying.cs" />
+    <Compile Include="Utils\TaskGroupModel.cs" />
+    <Compile Include="Utils\CompletedTaskGroupModel.cs" />
+    <Compile Include="Utils\TaskComparer.cs" />
+    <Compile Include="Utils\TaskListComparer.cs" />
+    <Compile Include="Utils\Preferences.cs" />
+    <Compile Include="Core\BackendManager.cs" />
+    <Compile Include="Core\Impl\InternalBackendManager.cs" />
+    <Compile Include="Core\Impl\InternalBackendManager.TaskListCollection.cs" />
+    <Compile Include="TaskPriority.cs" />
+    <Compile Include="INoteCore.cs" />
+    <Compile Include="ITaskCore.cs" />
+    <Compile Include="ITaskListCore.cs" />
+    <Compile Include="ITasqueCore.cs" />
     <Compile Include="NoteSupport.cs" />
-    <Compile Include="Task.cs" />
+    <Compile Include="Core\Impl\IContainer.cs" />
+    <Compile Include="Core\Impl\IInternalTasqueObject.cs" />
+    <Compile Include="Utils\TaskCompletionDateComparer.cs" />
+    <Compile Include="Utils\AllList.cs" />
+    <Compile Include="Core\TaskListType.cs" />
+    <Compile Include="IContainee.cs" />
   </ItemGroup>
   <ItemGroup>
     <Folder Include="DateFormatters\" />
     <Folder Include="Properties\" />
+    <Folder Include="Data\" />
+    <Folder Include="Core\" />
+    <Folder Include="Core\Impl\" />
+    <Folder Include="Utils\" />
   </ItemGroup>
   <Import Project="..\..\build\X.Common.targets" />
+  <ItemGroup>
+    <None Include="Data\IBackend.cs" />
+  </ItemGroup>
 </Project>
diff --git a/tasque.sln b/tasque.sln
index eff0066..09b5795 100644
--- a/tasque.sln
+++ b/tasque.sln
@@ -31,14 +31,14 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Gtk.Tasque.Columns", "src\A
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Gtk.Tasque.TimerCompleteColumns", 
"src\Addins\Gtk.Tasque.TimerCompleteColumns\Gtk.Tasque.TimerCompleteColumns.csproj", 
"{BFF82E44-DE40-441A-95C8-95269AB9C53D}"
 EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "tasque", "src\tasque\tasque.csproj", 
"{A70BD496-A280-4EF5-BBE8-254E0CA89C62}"
-EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MonoMac.Tasque", 
"src\MonoMac.Tasque\MonoMac.Tasque.csproj", "{67188C62-9332-4402-8702-E8BC1CCA8D2F}"
 EndProject
 Project("{9344bdbb-3e7f-41fc-a0dd-8665d75ee146}") = "po", "po\po.mdproj", 
"{51E65E50-71EE-4736-A47C-DA2ECF7F6793}"
 EndProject
 Project("{9344bdbb-3e7f-41fc-a0dd-8665d75ee146}") = "data", "data\data.mdproj", 
"{6F2F4BAA-3C60-464D-B757-9DD18FED0BAA}"
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "libtasque.Test", 
"tests\libtasque.Test\libtasque.Test.csproj", "{8820AFD6-D84B-4A13-A5DE-9EEEC92F3AC3}"
+EndProject
 Global
        GlobalSection(SolutionConfigurationPlatforms) = preSolution
                GtkLinuxDebug|Any CPU = GtkLinuxDebug|Any CPU
@@ -135,18 +135,15 @@ Global
                {7E8C2A02-418B-4659-9AF7-7017FD381F50}.GtkWinRelease|Any CPU.ActiveCfg = GtkRelease|Any CPU
                {7E8C2A02-418B-4659-9AF7-7017FD381F50}.MonoMacDebug|Any CPU.ActiveCfg = MonoMacDebug|Any CPU
                {7E8C2A02-418B-4659-9AF7-7017FD381F50}.MonoMacRelease|Any CPU.ActiveCfg = MonoMacRelease|Any 
CPU
-               {A70BD496-A280-4EF5-BBE8-254E0CA89C62}.GtkLinuxDebug|Any CPU.ActiveCfg = GtkLinuxDebug|Any CPU
-               {A70BD496-A280-4EF5-BBE8-254E0CA89C62}.GtkLinuxDebug|Any CPU.Build.0 = GtkLinuxDebug|Any CPU
-               {A70BD496-A280-4EF5-BBE8-254E0CA89C62}.GtkLinuxRelease|Any CPU.ActiveCfg = 
GtkLinuxRelease|Any CPU
-               {A70BD496-A280-4EF5-BBE8-254E0CA89C62}.GtkLinuxRelease|Any CPU.Build.0 = GtkLinuxRelease|Any 
CPU
-               {A70BD496-A280-4EF5-BBE8-254E0CA89C62}.GtkWinDebug|Any CPU.ActiveCfg = GtkWinDebug|Any CPU
-               {A70BD496-A280-4EF5-BBE8-254E0CA89C62}.GtkWinDebug|Any CPU.Build.0 = GtkWinDebug|Any CPU
-               {A70BD496-A280-4EF5-BBE8-254E0CA89C62}.GtkWinRelease|Any CPU.ActiveCfg = GtkWinRelease|Any CPU
-               {A70BD496-A280-4EF5-BBE8-254E0CA89C62}.GtkWinRelease|Any CPU.Build.0 = GtkWinRelease|Any CPU
-               {A70BD496-A280-4EF5-BBE8-254E0CA89C62}.MonoMacDebug|Any CPU.ActiveCfg = MonoMacDebug|Any CPU
-               {A70BD496-A280-4EF5-BBE8-254E0CA89C62}.MonoMacDebug|Any CPU.Build.0 = MonoMacDebug|Any CPU
-               {A70BD496-A280-4EF5-BBE8-254E0CA89C62}.MonoMacRelease|Any CPU.ActiveCfg = MonoMacRelease|Any 
CPU
-               {A70BD496-A280-4EF5-BBE8-254E0CA89C62}.MonoMacRelease|Any CPU.Build.0 = MonoMacRelease|Any CPU
+               {8820AFD6-D84B-4A13-A5DE-9EEEC92F3AC3}.GtkLinuxDebug|Any CPU.ActiveCfg = Debug|Any CPU
+               {8820AFD6-D84B-4A13-A5DE-9EEEC92F3AC3}.GtkLinuxDebug|Any CPU.Build.0 = Debug|Any CPU
+               {8820AFD6-D84B-4A13-A5DE-9EEEC92F3AC3}.GtkLinuxRelease|Any CPU.ActiveCfg = Debug|Any CPU
+               {8820AFD6-D84B-4A13-A5DE-9EEEC92F3AC3}.GtkWinDebug|Any CPU.ActiveCfg = Debug|Any CPU
+               {8820AFD6-D84B-4A13-A5DE-9EEEC92F3AC3}.GtkWinDebug|Any CPU.Build.0 = Debug|Any CPU
+               {8820AFD6-D84B-4A13-A5DE-9EEEC92F3AC3}.GtkWinRelease|Any CPU.ActiveCfg = Debug|Any CPU
+               {8820AFD6-D84B-4A13-A5DE-9EEEC92F3AC3}.MonoMacDebug|Any CPU.ActiveCfg = Debug|Any CPU
+               {8820AFD6-D84B-4A13-A5DE-9EEEC92F3AC3}.MonoMacDebug|Any CPU.Build.0 = Debug|Any CPU
+               {8820AFD6-D84B-4A13-A5DE-9EEEC92F3AC3}.MonoMacRelease|Any CPU.ActiveCfg = Debug|Any CPU
                {B19B9840-669D-4984-9772-E1F55193A67F}.GtkLinuxDebug|Any CPU.ActiveCfg = LinuxDebug|Any CPU
                {B19B9840-669D-4984-9772-E1F55193A67F}.GtkLinuxDebug|Any CPU.Build.0 = LinuxDebug|Any CPU
                {B19B9840-669D-4984-9772-E1F55193A67F}.GtkLinuxRelease|Any CPU.ActiveCfg = LinuxRelease|Any 
CPU
@@ -202,7 +199,6 @@ Global
                {CC8935CB-342C-4FDA-BAF1-24FA3EB53490}.MonoMacRelease|Any CPU.ActiveCfg = MonoMacRelease|Any 
CPU
                {CC8935CB-342C-4FDA-BAF1-24FA3EB53490}.MonoMacRelease|Any CPU.Build.0 = MonoMacRelease|Any CPU
                {CCCC10A5-662D-4788-82D3-25689F3D4D4F}.GtkLinuxDebug|Any CPU.ActiveCfg = GtkLinuxDebug|Any CPU
-               {CCCC10A5-662D-4788-82D3-25689F3D4D4F}.GtkLinuxDebug|Any CPU.Build.0 = GtkLinuxDebug|Any CPU
                {CCCC10A5-662D-4788-82D3-25689F3D4D4F}.GtkLinuxRelease|Any CPU.ActiveCfg = 
GtkLinuxRelease|Any CPU
                {CCCC10A5-662D-4788-82D3-25689F3D4D4F}.GtkLinuxRelease|Any CPU.Build.0 = GtkLinuxRelease|Any 
CPU
                {CCCC10A5-662D-4788-82D3-25689F3D4D4F}.GtkWinDebug|Any CPU.ActiveCfg = GtkWinDebug|Any CPU
@@ -232,8 +228,8 @@ Global
                {FBDF2B11-0EEE-4463-A282-009AC1F7FC76} = {E2E6EE06-C957-4D1E-85CA-90F3773597DE}
        EndGlobalSection
        GlobalSection(MonoDevelopProperties) = preSolution
-               StartupItem = src\tasque\tasque.csproj
-               version = 0.1.13
+               StartupItem = src\Gtk.Tasque\Gtk.Tasque.csproj
+               version = 0.2.0
        EndGlobalSection
        GlobalSection(SolutionProperties) = preSolution
                HideSolutionNode = FALSE
diff --git a/src/libtasque/TaskComparer.cs b/tests/DummyBackendTest.cs
similarity index 76%
rename from src/libtasque/TaskComparer.cs
rename to tests/DummyBackendTest.cs
index 1285fe1..d3cc958 100644
--- a/src/libtasque/TaskComparer.cs
+++ b/tests/DummyBackendTest.cs
@@ -1,10 +1,10 @@
 //
-// TaskComparer.cs
+// DummyBackend.cs
 //
 // Author:
 //       Antonius Riha <antoniusriha gmail com>
 //
-// Copyright (c) 2012 Antonius Riha
+// Copyright (c) 2013 Antonius Riha
 //
 // Permission is hereby granted, free of charge, to any person obtaining a copy
 // of this software and associated documentation files (the "Software"), to deal
@@ -23,18 +23,26 @@
 // 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.Generic;
+using System;
+using NUnit.Framework;
+using Tasque.Backends.Dummy;
 
-namespace Tasque
+namespace Tasque.Tests
 {
-       public class TaskComparer : Comparer<ITask>
+       [TestFixture()]
+       public class DummyBackendTest
        {
-               public override int Compare (ITask x, ITask y)
+               [Test()]
+               public void GetAll ()
                {
-                       if (x == null || y == null)
-                               return 0;
-                       
-                       return (x.CompareTo (y));
+                       // setup
+                       var backend = new DummyBackend ();
+
+                       // act
+                       var lists = backend.GetAll ();
+
+                       // check
+                       Assert.IsNotEmpty (lists);
                }
        }
 }
diff --git a/tests/TaskParserFixture.cs b/tests/TaskParserFixture.cs
index 9be2f8b..a1f0393 100644
--- a/tests/TaskParserFixture.cs
+++ b/tests/TaskParserFixture.cs
@@ -23,6 +23,7 @@
 
 using System;
 using NUnit.Framework;
+using Tasque.DateFormatters;
 
 namespace Tasque.Tests {
 
diff --git a/tests/libtasque.Test/Core/Impl/NoteTest.cs b/tests/libtasque.Test/Core/Impl/NoteTest.cs
new file mode 100644
index 0000000..7c2c2f7
--- /dev/null
+++ b/tests/libtasque.Test/Core/Impl/NoteTest.cs
@@ -0,0 +1,129 @@
+//
+// NoteTest.cs
+//
+// Author:
+//       Antonius Riha <antoniusriha gmail com>
+//
+// Copyright (c) 2013 Antonius Riha
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using NUnit.Framework;
+using Moq;
+using Tasque.Data;
+
+namespace Tasque.Core.Impl
+{
+       [TestFixture]
+       public class NoteTest
+       {
+               [SetUp]
+               public void Setup ()
+               {
+                       noteRepoMock = new Mock<INoteRepository> ();
+                       note = new Note (noteRepoMock.Object);
+               }
+
+               [Test]
+               public void CreateNote ()
+               {
+                       note = new Note (noteRepoMock.Object);
+                       Assert.AreEqual (noteRepoMock.Object, note.Repository, "#A0");
+                       Assert.IsNull (note.Id, "#A1");
+                       Assert.IsNull (note.Text, "#A2");
+                       Assert.IsEmpty (note.InternalContainers, "#A3");
+                       Assert.IsTrue (note.IsBackendDetached, "#A4");
+               }
+
+               [Test]
+               public void CreateNoteFromRepo ()
+               {
+                       var id = "x344";
+                       var note = Note.CreateNote (id, noteRepoMock.Object);
+
+                       Assert.AreEqual (noteRepoMock.Object, note.Repository, "#A0");
+                       Assert.AreEqual (note.Id, id, "#A1");
+                       Assert.IsNull (note.Text, "#A2");
+                       Assert.IsEmpty (note.InternalContainers, "#A3");
+                       Assert.IsTrue (note.IsBackendDetached, "#A4");
+               }
+
+               [Test]
+               public void SetTextWithDetachedBackend ()
+               {
+                       Assert.IsTrue (note.IsBackendDetached, "#A0");
+                       var s = string.Empty;
+                       noteRepoMock.Setup (r => r.UpdateText (note, s));
+
+                       var text1 = "This is the note text.";
+                       note.Text = text1;
+                       Assert.AreEqual (text1, note.Text, "#A1");
+                       note.Text = null;
+                       Assert.IsNull (note.Text, "#A2");
+                       noteRepoMock.Verify (r => r.UpdateText (note, s),
+                                            Times.Never ());
+               }
+
+               [Test]
+               public void SetTextWithAttachedBackend ()
+               {
+                       int propChangedCount = 0, propChangingCount = 0;
+                       note.PropertyChanged += (sender, e) => {
+                               Assert.AreEqual ("Text", e.PropertyName, "#A0");
+                               propChangingCount++;
+                       };
+                       note.PropertyChanging += (sender, e) => {
+                               Assert.AreEqual ("Text", e.PropertyName, "#A1");
+                               propChangedCount++;
+                       };
+
+                       note.AttachBackend (null);
+                       Assert.IsFalse (note.IsBackendDetached, "#B0");
+                       
+                       var text1 = "This is the note text.";
+                       noteRepoMock.Setup (
+                               r => r.UpdateText (note, text1)).Returns (text1).Verifiable ("#C0");
+                       note.Text = text1;
+                       Assert.AreEqual (text1, note.Text, "#C1");
+                       Assert.AreEqual (1, propChangedCount, "#C2");
+                       Assert.AreEqual (1, propChangingCount, "#C3");
+
+                       string text2 = null;
+                       noteRepoMock.Setup (
+                               r => r.UpdateText (note, text2)).Returns (text2).Verifiable ("#D0");
+                       note.Text = text2;
+                       Assert.IsNull (note.Text, "#D1");
+                       Assert.AreEqual (2, propChangedCount, "#D2");
+                       Assert.AreEqual (2, propChangingCount, "#D3");
+
+                       noteRepoMock.Setup (r => r.UpdateText (note, text2));
+                       note.Text = text2;
+                       noteRepoMock.Verify (r => r.UpdateText (note, text2),
+                                            Times.Once (), "#E0");
+                       Assert.IsNull (note.Text, "#E1");
+                       Assert.AreEqual (2, propChangedCount, "#E2");
+                       Assert.AreEqual (2, propChangingCount, "#E3");
+                       
+                       noteRepoMock.Verify ();
+               }
+
+               Note note;
+               Mock<INoteRepository> noteRepoMock;
+       }
+}
diff --git a/tests/libtasque.Test/Core/Impl/TaskBackendAttachedTest.cs 
b/tests/libtasque.Test/Core/Impl/TaskBackendAttachedTest.cs
new file mode 100644
index 0000000..4927c24
--- /dev/null
+++ b/tests/libtasque.Test/Core/Impl/TaskBackendAttachedTest.cs
@@ -0,0 +1,93 @@
+//
+// TaskBackendAttachedTest.cs
+//
+// Author:
+//       Antonius Riha <antoniusriha gmail com>
+//
+// Copyright (c) 2013 Antonius Riha
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using NUnit.Framework;
+
+namespace Tasque.Core.Impl
+{
+       [TestFixture]
+       public class TaskBackendAttachedTest : TaskTest
+       {
+               [Test]
+               public void Activate ()
+               {
+                       Activate (false);
+               }
+
+               [Test]
+               public void Complete ()
+               {
+                       Complete (false);
+               }
+
+               [Test]
+               public void Discard ()
+               {
+                       Discard (false);
+               }
+               
+               [Test]
+               public void CreateNote_NoneNoteSupport ()
+               {
+                       CreateNote (false, NoteSupport.None);
+               }
+               
+               [Test]
+               public void CreateNote_NoneNoteSupport_WithText ()
+               {
+                       CreateNote (false, NoteSupport.None, true, "Note text");
+               }
+               
+               [Test]
+               public void CreateNote_SingleNoteSupport ()
+               {
+                       CreateNote (false, NoteSupport.Single);
+               }
+               
+               [Test]
+               public void CreateNote_SingleNoteSupport_WithText ()
+               {
+                       CreateNote (false, NoteSupport.Single, true, "Note text");
+               }
+               
+               [Test]
+               public void CreateNote_MultipleNoteSupport ()
+               {
+                       CreateNote (false, NoteSupport.Multiple);
+               }
+               
+               [Test]
+               public void CreateNote_MultipleNoteSupport_WithText ()
+               {
+                       CreateNote (false, NoteSupport.Multiple, true, "Note text");
+               }
+
+               [Test]
+               public void Refresh ()
+               {
+                       Refresh (false);
+               }
+       }
+}
diff --git a/src/libtasque/CategoryComparer.cs b/tests/libtasque.Test/Core/Impl/TaskBackendDetachedTest.cs
similarity index 50%
copy from src/libtasque/CategoryComparer.cs
copy to tests/libtasque.Test/Core/Impl/TaskBackendDetachedTest.cs
index b81fcfa..9d6f695 100644
--- a/src/libtasque/CategoryComparer.cs
+++ b/tests/libtasque.Test/Core/Impl/TaskBackendDetachedTest.cs
@@ -1,10 +1,10 @@
 //
-// CategoryComparer.cs
+// TaskBackendDetached.cs
 //
 // Author:
 //       Antonius Riha <antoniusriha gmail com>
 //
-// Copyright (c) 2012 Antonius Riha
+// Copyright (c) 2013 Antonius Riha
 //
 // Permission is hereby granted, free of charge, to any person obtaining a copy
 // of this software and associated documentation files (the "Software"), to deal
@@ -23,23 +23,71 @@
 // 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.Generic;
+using NUnit.Framework;
 
-namespace Tasque
+namespace Tasque.Core.Impl
 {
-       public class CategoryComparer : Comparer<ICategory>
+       [TestFixture]
+       public class TaskBackendDetachedTest : TaskTest
        {
-               public override int Compare (ICategory x, ICategory y)
-               {
-                       if (x == null || y == null)
-                               return 0;
-                       
-                       if (x is AllCategory)
-                               return -1;
-                       else if (y is AllCategory)
-                               return 1;
-                       
-                       return (x.Name.CompareTo (y.Name));
+               [Test]
+               public void Activate ()
+               {
+                       Activate (true);
+               }
+               
+               [Test]
+               public void Complete ()
+               {
+                       Complete (true);
+               }
+
+               [Test]
+               public void Discard ()
+               {
+                       Discard (true);
+               }
+               
+               [Test]
+               public void CreateNote_NoneNoteSupport ()
+               {
+                       CreateNote (true, NoteSupport.None);
+               }
+
+               [Test]
+               public void CreateNote_NoneNoteSupport_WithText ()
+               {
+                       CreateNote (true, NoteSupport.None, true, "Note text");
+               }
+
+               [Test]
+               public void CreateNote_SingleNoteSupport ()
+               {
+                       CreateNote (true, NoteSupport.Single);
+               }
+
+               [Test]
+               public void CreateNote_SingleNoteSupport_WithText ()
+               {
+                       CreateNote (true, NoteSupport.Single, true, "Note text");
+               }
+
+               [Test]
+               public void CreateNote_MultipleNoteSupport ()
+               {
+                       CreateNote (true, NoteSupport.Multiple);
+               }
+
+               [Test]
+               public void CreateNote_MultipleNoteSupport_WithText ()
+               {
+                       CreateNote (true, NoteSupport.Multiple, true, "Note text");
+               }
+
+               [Test]
+               public void Refresh ()
+               {
+                       Refresh (true);
                }
        }
 }
diff --git a/tests/libtasque.Test/Core/Impl/TaskTest.cs b/tests/libtasque.Test/Core/Impl/TaskTest.cs
new file mode 100644
index 0000000..53be56c
--- /dev/null
+++ b/tests/libtasque.Test/Core/Impl/TaskTest.cs
@@ -0,0 +1,331 @@
+//
+// TaskTest.cs
+//
+// Author:
+//       Antonius Riha <antoniusriha gmail com>
+//
+// Copyright (c) 2013 Antonius Riha
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using System.Collections.Specialized;
+using NUnit.Framework;
+using Moq;
+using Tasque.Data;
+
+namespace Tasque.Core.Impl
+{
+       using NoteCollectionRepo = ICollectionRepository<INote, ITask>;
+       using TaskCollectionRepo = ICollectionRepository<ITask, ITask>;
+
+       [TestFixture]
+       public class TaskTest
+       {
+               protected Task Task { get; set; }
+               protected string InitialText { get; set; }
+               protected Mock<ITaskRepository> TaskRepoMock { get; set; }
+               protected Mock<INoteRepository> NoteRepoMock { get; set; }
+
+               [SetUp]
+               public void Setup ()
+               {
+                       TaskRepoMock = new Mock<ITaskRepository> ();
+                       NoteRepoMock = new Mock<INoteRepository> ();
+                       InitialText = "Task1";
+                       Task = new Task (InitialText, TaskRepoMock.Object,
+                                        NoteRepoMock.Object);
+               }
+               
+               [Test]
+               public void CreateTask ()
+               {
+                       TaskRepoMock.Setup (r => r.UpdateText (
+                               It.IsAny<ITask> (), InitialText));
+                       Task = new Task (InitialText, TaskRepoMock.Object,
+                                        NoteRepoMock.Object);
+                       TaskRepoMock.Verify (r => r.UpdateText (
+                               It.IsAny<ITask> (), InitialText), Times.Never (), "#A0");
+                       Assert.AreEqual (TaskRepoMock.Object, Task.Repository, "#A1");
+                       Assert.IsNull (Task.Id, "#A2");
+                       Assert.AreEqual (InitialText, Task.Text, "#A3");
+                       Assert.IsEmpty (((IInternalContainee<TaskList>)Task)
+                                       .InternalContainers, "#A4");
+                       Assert.IsEmpty (((IInternalContainee<Task>)Task)
+                                       .InternalContainers, "#A5");
+                       Assert.IsTrue (Task.IsBackendDetached, "#A6");
+                       Assert.AreEqual (DateTime.MinValue, Task.DueDate, "#A7");
+                       Assert.AreEqual (DateTime.MinValue, Task.CompletionDate, "#A8");
+                       Assert.IsFalse (Task.HasNotes, "#A9");
+                       Assert.IsFalse (Task.IsComplete, "#A10");
+                       Assert.AreEqual (TaskPriority.None, Task.Priority, "#A11");
+                       Assert.AreEqual (TaskState.Active, Task.State, "#A12");
+               }
+               
+               [Test]
+               public void CreateTaskFromRepo ()
+               {
+                       var id = "ols4";
+                       TaskRepoMock.Setup (r => r.UpdateText (
+                               It.IsAny<ITask> (), InitialText));
+                       var task = Task.CreateTask (id, InitialText,
+                       TaskRepoMock.Object, NoteRepoMock.Object);
+                       TaskRepoMock.Verify (r => r.UpdateText (
+                               It.IsAny<ITask> (), InitialText), Times.Never (), "#A0");
+                       Assert.AreEqual (id, task.Id, "#A1");
+                       Assert.AreEqual (InitialText, task.Text, "#A2");
+               }
+               
+               [Test]
+               public void CreateCompletedTaskFromRepo ()
+               {
+                       var id = "ols4";
+                       var completionDate = DateTime.Now;
+                       TaskRepoMock.Setup (r => r.UpdateText (
+                               It.IsAny<ITask> (), InitialText));
+                       var task = Task.CreateCompletedTask (id, InitialText,
+                       completionDate, TaskRepoMock.Object, NoteRepoMock.Object);
+                       TaskRepoMock.Verify (r => r.UpdateText (
+                               It.IsAny<ITask> (), InitialText), Times.Never (), "#A0");
+                       Assert.AreEqual (id, task.Id, "#A1");
+                       Assert.AreEqual (InitialText, task.Text, "#A2");
+                       Assert.AreEqual (completionDate, task.CompletionDate, "#A3");
+                       Assert.IsTrue (task.IsComplete, "#A4");
+               }
+               
+               [Test]
+               public void CreateDiscardedTaskFromRepo ()
+               {
+                       var id = "ols4";
+                       TaskRepoMock.Setup (r => r.UpdateText (
+                               It.IsAny<ITask> (), InitialText));
+                       TaskRepoMock.SetupGet (r => r.SupportsDiscarding)
+                               .Returns (true).Verifiable ("#A0");
+                       var task = Task.CreateDiscardedTask (id, InitialText,
+                       TaskRepoMock.Object, NoteRepoMock.Object);
+                       TaskRepoMock.Verify (r => r.UpdateText (
+                               It.IsAny<ITask> (), InitialText), Times.Never (), "#A1");
+                       Assert.AreEqual (id, task.Id, "#A2");
+                       Assert.AreEqual (InitialText, task.Text, "#A3");
+                       Assert.AreEqual (TaskState.Discarded, task.State, "#A4");
+                       
+                       TaskRepoMock.Setup (r => r.SupportsDiscarding)
+                               .Returns (false).Verifiable ("#A5");
+                       
+                       Assert.Throws<NotSupportedException> (delegate {
+                               Task.CreateDiscardedTask (id, InitialText, TaskRepoMock.Object,
+                                                         NoteRepoMock.Object);
+                       }, "#A6");
+                       TaskRepoMock.Verify ();
+               }
+
+               protected void Activate (bool detached)
+               {
+                       Task = Task.CreateCompletedTask ("ijj", "Text 1", DateTime.Now,
+                               TaskRepoMock.Object, NoteRepoMock.Object);
+                       SetupDetachedOrAttached (Task, detached, "#A0");
+                       
+                       int activatingCount = 0, activatedCount = 0;
+                       Task.Activating += delegate {
+                               Assert.AreEqual (activatedCount, activatingCount++, "#A1");
+                       };
+                       Task.Activated += delegate {
+                               Assert.AreEqual (activatingCount, ++activatedCount, "#A2");
+                       };
+
+                       TaskRepoMock.Setup (r => r.Activate (Task));
+                       Task.Activate ();
+                       
+                       var times = detached ? Times.Never () : Times.Once ();
+                       TaskRepoMock.Verify (r => r.Activate (Task), times, "#A3");
+                       Assert.AreEqual (DateTime.MinValue, Task.CompletionDate, "#A4");
+                       Assert.AreEqual (TaskState.Active, Task.State, "#A5");
+                       Assert.IsFalse (Task.IsComplete, "#A6");
+               }
+
+               protected void Complete (bool detached)
+               {
+                       SetupDetachedOrAttached (Task, detached, "#A0");
+                       
+                       int completingCount = 0, completedCount = 0;
+                       Task.Completing += delegate {
+                               Assert.AreEqual (completedCount, completingCount++, "#A1");
+                       };
+                       Task.Completed += delegate {
+                               Assert.AreEqual (completingCount, ++completedCount, "#A2");
+                       };
+
+                       var now = DateTime.Now;
+                       TaskRepoMock.Setup (r => r.Complete (Task, It.IsAny<DateTime> ()))
+                               .Returns (now);
+                       Task.Complete ();
+
+                       var times = detached ? Times.Never () : Times.Once ();
+                       TaskRepoMock.Verify (r => r.Complete (Task, It.IsAny<DateTime> ()),
+                                            times, "#A3");
+
+                       if (detached) {
+                               Assert.LessOrEqual (now, Task.CompletionDate, "#A4a");
+                               Assert.GreaterOrEqual (
+                                       DateTime.Now, Task.CompletionDate, "#A4b");
+                       } else
+                               Assert.AreEqual (now, Task.CompletionDate, "#A4");
+                       Assert.AreEqual (TaskState.Completed, Task.State, "#A5");
+                       Assert.IsTrue (Task.IsComplete, "#A6");
+               }
+
+               protected void Discard (bool detached)
+               {
+                       TaskRepoMock.Setup (r => r.SupportsDiscarding)
+                               .Returns (true);
+                       Task = new Task ("k", TaskRepoMock.Object, NoteRepoMock.Object);
+                       SetupDetachedOrAttached (Task, detached, "#A0");
+                       
+                       int discardingCount = 0, discardedCount = 0;
+                       Task.Discarding += delegate {
+                               Assert.AreEqual (discardedCount, discardingCount++, "#A1");
+                       };
+                       Task.Discarded += delegate {
+                               Assert.AreEqual (discardingCount, ++discardedCount, "#A2");
+                       };
+
+                       TaskRepoMock.Setup (r => r.Discard (Task));
+                       Task.Discard ();
+                       
+                       var times = detached ? Times.Never () : Times.Once ();
+                       TaskRepoMock.Verify (r => r.Discard (Task),
+                                            times, "#A3");
+                       Assert.AreEqual (TaskState.Discarded, Task.State, "#A4");
+               }
+
+               protected void CreateNote (bool detached, NoteSupport noteSupport,
+                                          bool withText = false, string text = null)
+               {
+                       TaskRepoMock.Setup (r => r.NoteSupport).Returns (noteSupport);
+                       Task = new Task ("Task1", TaskRepoMock.Object,
+                                        NoteRepoMock.Object);
+                       SetupDetachedOrAttached (Task, detached, "#A0");
+                       TaskRepoMock.Setup (r => r.AddNew (Task, It.IsAny<INote> ()));
+                       TaskRepoMock.Setup (r => r.UpdateNote (Task, It.IsAny<INote> ()))
+                               .Returns ((ITask t, INote n) => n);
+                       
+                       if (noteSupport == NoteSupport.None)
+                               CreateNote_NoneNoteSupport (text, withText, "#B");
+                       else if (noteSupport == NoteSupport.Single)
+                               CreateNote_SingleNoteSupport (detached, text, withText, "#B");
+                       else
+                               CreateNote_MultipleNoteSupport (detached, text, withText, "#B");
+               }
+
+               protected void Refresh (bool detached)
+               {
+                       Assert.Inconclusive ();
+               }
+
+               void CreateNote_NoneNoteSupport (
+                       string text, bool withText, string msg)
+               {
+                       if (withText) {
+                               Assert.Throws<NotSupportedException> (delegate {
+                                       Task.CreateNote (text);
+                               }, msg + 0);
+                       } else {
+                               Assert.Throws<NotSupportedException> (delegate {
+                                       Task.CreateNote ();
+                               }, msg + 1);
+                       }
+                       TaskRepoMock.Verify (r => r.AddNew (Task, It.IsAny<INote> ()),
+                                            Times.Never (), msg + 2);
+                       TaskRepoMock.Verify (r => r.UpdateNote (Task, It.IsAny<INote> ()),
+                                            Times.Never (), msg + 3);
+               }
+
+               void CreateNote_SingleNoteSupport (
+                       bool detached, string text, bool withText, string msg)
+               {
+                       if (!withText)
+                               text = null;
+
+                       int propChangingCount = 0, propChangedCount = 0;
+                       Task.PropertyChanging += (sender, e) => {
+                               Assert.AreEqual ("Note", e.PropertyName, msg + 0);
+                               Assert.AreEqual (propChangedCount, propChangingCount++,
+                                                msg + 1);
+                       };
+                       Task.PropertyChanging += (sender, e) => {
+                               Assert.AreEqual ("Note", e.PropertyName, msg + 2);
+                               Assert.AreEqual (++propChangedCount, propChangingCount,
+                                                msg + 3);
+                       };
+
+                       var note = withText ? Task.CreateNote (text) : Task.CreateNote ();
+
+                       Assert.IsNotNull (note, msg + 4);
+                       Assert.AreEqual (note, Task.Note, msg + 5);
+                       Assert.AreEqual (text, note.Text, msg + 6);
+                       Assert.AreEqual (1, propChangingCount, msg + 7);
+                       Assert.AreEqual (1, propChangedCount, msg + 8);
+                       
+                       TaskRepoMock.Verify (r => r.AddNew (Task, It.IsAny<INote> ()),
+                                            Times.Never (), msg + 9);
+                       var times = detached ? Times.Never () : Times.Once ();
+                       TaskRepoMock.Verify (r => r.UpdateNote (Task, It.IsAny<INote> ()),
+                                            times, msg + 10);
+               }
+
+               void CreateNote_MultipleNoteSupport (
+                       bool detached, string text, bool withText, string msg)
+               {
+                       if (!withText)
+                               text = null;
+
+                       INote note = null, noteFromChangeEvent = null;
+                       var collectionChangedCount = 0;
+                       Task.Notes.CollectionChanged += (sender, e) => {
+                               collectionChangedCount++;
+                               Assert.AreEqual (NotifyCollectionChangedAction.Add, e.Action,
+                                                msg + 0);
+                               noteFromChangeEvent = e.NewItems [0] as INote;
+                       };
+                       
+                       note = withText ? Task.CreateNote (text) : Task.CreateNote ();
+
+                       Assert.AreEqual (note, noteFromChangeEvent, msg + 1);
+                       Assert.IsNotNull (note, msg + 2);
+                       Assert.Contains (note, Task.Notes, msg + 3);
+                       Assert.AreEqual (text, note.Text, msg + 4);
+                       Assert.AreEqual (1, collectionChangedCount, msg + 5);
+
+                       var times = detached ? Times.Never () : Times.Once ();
+                       TaskRepoMock.Verify (r => r.AddNew (Task, It.IsAny<INote> ()),
+                                            times, msg + 6);
+                       TaskRepoMock.Verify (r => r.UpdateNote (Task, It.IsAny<INote> ()),
+                                            Times.Never (), msg + 7);
+               }
+
+               void SetupDetachedOrAttached (Task task, bool detached, string msg)
+               {
+                       if (detached)
+                               Assert.IsTrue (task.IsBackendDetached, msg);
+                       else {
+                               task.AttachBackend (null);
+                               Assert.IsFalse (task.IsBackendDetached, msg);
+                       }
+               }
+       }
+}
diff --git a/src/libtasque/CategoryComparer.cs 
b/tests/libtasque.Test/Core/Impl/TasqueObjectCollectionSharingTest.cs
similarity index 58%
rename from src/libtasque/CategoryComparer.cs
rename to tests/libtasque.Test/Core/Impl/TasqueObjectCollectionSharingTest.cs
index b81fcfa..b252012 100644
--- a/src/libtasque/CategoryComparer.cs
+++ b/tests/libtasque.Test/Core/Impl/TasqueObjectCollectionSharingTest.cs
@@ -1,10 +1,10 @@
 //
-// CategoryComparer.cs
+// TasqueObjectCollectionTest2.cs
 //
 // Author:
 //       Antonius Riha <antoniusriha gmail com>
 //
-// Copyright (c) 2012 Antonius Riha
+// Copyright (c) 2013 Antonius Riha
 //
 // Permission is hereby granted, free of charge, to any person obtaining a copy
 // of this software and associated documentation files (the "Software"), to deal
@@ -23,23 +23,43 @@
 // 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.Generic;
+using System;
+using NUnit.Framework;
+using Moq;
+using Tasque.Data;
 
-namespace Tasque
+namespace Tasque.Core.Impl
 {
-       public class CategoryComparer : Comparer<ICategory>
+       using IContainerRepo = ICollectionRepository<ITasqueCore, ITasqueCore>;
+       using Container =
+               TasqueObject<ICollectionRepository<ITasqueCore, ITasqueCore>>;
+       using TasqueCollection = TasqueObjectCollection<ITasqueCore,
+       TasqueObject<ICollectionRepository<ITasqueCore, ITasqueCore>>,
+       ICollectionRepository<ITasqueCore, ITasqueCore>>;
+
+       [TestFixture]
+       public class TasqueObjectCollectionSharingTest
        {
-               public override int Compare (ICategory x, ICategory y)
+               [SetUp]
+               public void Setup ()
+               {
+
+               }
+
+               [Test()]
+               public void GetAll ()
                {
-                       if (x == null || y == null)
-                               return 0;
-                       
-                       if (x is AllCategory)
-                               return -1;
-                       else if (y is AllCategory)
-                               return 1;
-                       
-                       return (x.Name.CompareTo (y.Name));
+                       Assert.Inconclusive ();
                }
+
+               [Test()]
+               public void GetBy ()
+               {
+
+               }
+
+               Mock<Container> container;
+               Mock<IContainerRepo> containerRepo;
+               TasqueCollection collection;
        }
 }
diff --git a/tests/libtasque.Test/Core/Impl/TasqueObjectCollectionTest.cs 
b/tests/libtasque.Test/Core/Impl/TasqueObjectCollectionTest.cs
new file mode 100644
index 0000000..a0a8d03
--- /dev/null
+++ b/tests/libtasque.Test/Core/Impl/TasqueObjectCollectionTest.cs
@@ -0,0 +1,84 @@
+//
+// TasqueObjectCollectionTest.cs
+//
+// Author:
+//       Antonius Riha <antoniusriha gmail com>
+//
+// Copyright (c) 2013 Antonius Riha
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using NUnit.Framework;
+using Moq;
+using Tasque.Data;
+
+namespace Tasque.Core.Impl
+{
+       using IContainerRepo = ICollectionRepository<ITasqueCore, ITasqueCore>;
+       using Container =
+               TasqueObject<ICollectionRepository<ITasqueCore, ITasqueCore>>;
+       using TasqueCollection = TasqueObjectCollection<ITasqueCore,
+               TasqueObject<ICollectionRepository<ITasqueCore, ITasqueCore>>,
+               ICollectionRepository<ITasqueCore, ITasqueCore>>;
+
+       [TestFixture]
+       public class TasqueObjectCollectionTest
+       {
+               [SetUp]
+               public void Setup ()
+               {
+                       containerRepo = new Mock<IContainerRepo> ();
+                       container = new Mock<Container> (containerRepo.Object) {
+                               CallBase = true
+                       };
+                       collection = new TasqueCollection (container.Object);
+               }
+
+               [Test]
+               public void Add_CannotShareItemsWithOtherCollections ()
+               {
+                       containerRepo.SetupGet (r => r
+                               .SupportsSharingItemsWithOtherCollections).Returns (false);
+                       var tasqueCoreMock = new Mock<ITasqueCore> ();
+                       Assert.Throws<NotSupportedException> (delegate {
+                               collection.Add (tasqueCoreMock.Object);
+                       });
+               }
+
+               [Test]
+               public void Add_CanShareItemsWithOtherCollections ()
+               {
+                       Assert.Inconclusive ();
+               }
+
+               [Test]
+               public void GetAll ()
+               {}
+
+               [Test]
+               public void GetBy ()
+               {
+
+               }
+
+               Mock<Container> container;
+               Mock<IContainerRepo> containerRepo;
+               TasqueCollection collection;
+       }
+}
diff --git a/tests/libtasque.Test/Core/Impl/TasqueObjectTest.cs 
b/tests/libtasque.Test/Core/Impl/TasqueObjectTest.cs
new file mode 100644
index 0000000..0f6912a
--- /dev/null
+++ b/tests/libtasque.Test/Core/Impl/TasqueObjectTest.cs
@@ -0,0 +1,192 @@
+//
+// TasqueObjectTest.cs
+//
+// Author:
+//       Antonius Riha <antoniusriha gmail com>
+//
+// Copyright (c) 2013 Antonius Riha
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using NUnit.Framework;
+using Moq;
+using Tasque.Data;
+
+namespace Tasque.Core.Impl
+{
+       using TasqueObject = TasqueObject<IRepository>;
+       using TasqueObjectMock = Mock<TasqueObject<IRepository>>;
+
+       [TestFixture]
+       public class TasqueObjectTest
+       {
+               [SetUp]
+               public void Setup ()
+               {
+                       repoMock = new Mock<IRepository> ();
+                       tasqueObjectMock = new TasqueObjectMock (repoMock.Object) {
+                               CallBase = true
+                       };
+                       propChangingCount = propChangedCount = 0;
+               }
+
+               [Test]
+               public void CreateTasqueObject ()
+               {
+                       var tasqueObject = tasqueObjectMock.Object;
+                       Assert.IsNull (tasqueObject.Id, "#A0");
+                       Assert.AreEqual (repoMock.Object, tasqueObject.Repository, "#A1");
+               }
+
+               [Test]
+               public void SetId ()
+               {
+                       var tasqueObject = tasqueObjectMock.Object;
+                       var id = "l558";
+                       tasqueObject.SetId (id);
+                       Assert.AreEqual (id, tasqueObject.Id, "#A0");
+               }
+
+               [Test]
+               public void SetProperty ()
+               {
+                       var tasqueObject = tasqueObjectMock.Object;
+                       tasqueObjectMock.SetupGet (t => t.IsBackendDetached)
+                               .Returns (false);
+                       var propertyName = "Property";
+                       var curValue = "oldValue";
+                       var repoMock = new Mock<IRepo> ();
+                       Action<string> setVal = x => curValue = x;
+                       Func<TasqueObject, string, string> update
+                               = repoMock.Object.Update;
+
+                       SetupNotifyEventsTest (tasqueObject, propertyName, "#A");
+
+                       var value = "newValue";
+                       repoMock.Setup (r => r.Update (tasqueObject, value))
+                               .Returns (value);
+                       tasqueObject.SetProperty<string, TasqueObject> (
+                               propertyName, value, curValue, setVal, update);
+                       repoMock.Verify (r => r.Update (tasqueObject, value),
+                                        Times.Once (), "#B0");
+                       Assert.AreEqual (curValue, value, "#B1");
+                       Assert.AreEqual (1, propChangingCount, "#B2");
+                       Assert.AreEqual (1, propChangedCount, "#B3");
+
+                       // try setting the same value again
+                       tasqueObject.SetProperty<string, TasqueObject> (
+                               propertyName, value, curValue, setVal, update);
+                       repoMock.Verify (r => r.Update (tasqueObject, value),
+                                        Times.Once (), "#C0");
+                       Assert.AreEqual (curValue, value, "#C1");
+                       Assert.AreEqual (1, propChangingCount, "#C2");
+                       Assert.AreEqual (1, propChangedCount, "#C3");
+               }
+
+               [Test]
+               public void SetPropertyWithRepoIntervention ()
+               {
+                       var tasqueObject = tasqueObjectMock.Object;
+                       tasqueObjectMock.SetupGet (t => t.IsBackendDetached)
+                               .Returns (false);
+                       var propertyName = "Property";
+                       var curValue = "oldValue";
+                       var repoMock = new Mock<IRepo> ();
+                       Action<string> setVal = x => curValue = x;
+                       Func<TasqueObject, string, string> update
+                               = repoMock.Object.Update;
+
+                       SetupNotifyEventsTest (tasqueObject, propertyName, "#A");
+
+                       // setting a new value that is changed by the repo
+                       var newValue = "I'll be changed";
+                       var changedNewValue = newValue.Replace ("'", "\\'");
+                       repoMock.Setup (r => r.Update (tasqueObject, newValue))
+                               .Returns (changedNewValue);
+                       tasqueObject.SetProperty<string, TasqueObject> (
+                               propertyName, newValue, curValue, setVal, update);
+                       repoMock.Verify (r => r.Update (tasqueObject, newValue),
+                                        Times.Once (), "#B0");
+                       Assert.AreEqual (curValue, changedNewValue, "#B1");
+                       Assert.AreEqual (1, propChangingCount, "#B2");
+                       Assert.AreEqual (1, propChangedCount, "#B3");
+                       
+                       // setting a new value that is changed to the old value by the repo
+                       tasqueObject.SetProperty<string, TasqueObject> (
+                               propertyName, newValue, curValue, setVal, update);
+                       repoMock.Verify (r => r.Update (tasqueObject, newValue),
+                                        Times.Exactly (2), "#C0");
+                       Assert.AreEqual (curValue, changedNewValue, "#C1");
+                       Assert.AreEqual (1, propChangingCount, "#C2");
+                       Assert.AreEqual (1, propChangedCount, "#C3");
+               }
+
+               [Test]
+               public void SetPropertyWithBackendDetached ()
+               {
+                       var tasqueObject = tasqueObjectMock.Object;
+                       tasqueObjectMock.SetupGet (t => t.IsBackendDetached)
+                               .Returns (true);
+                       var propertyName = "Property";
+                       var curValue = "oldValue";
+                       var repoMock = new Mock<IRepo> ();
+                       Action<string> setVal = x => curValue = x;
+                       Func<TasqueObject, string, string> update
+                               = repoMock.Object.Update;
+                       
+                       SetupNotifyEventsTest (tasqueObject, propertyName, "#A");
+
+                       var newValue = "value 378";
+                       repoMock.Setup (r => r.Update (tasqueObject, newValue));
+                       tasqueObject.SetProperty<string, TasqueObject> (
+                               propertyName, newValue, curValue, setVal, update);
+                       repoMock.Verify (r => r.Update (tasqueObject, newValue),
+                                        Times.Never (), "#B0");
+                       Assert.AreEqual (curValue, newValue, "#B1");
+                       Assert.AreEqual (1, propChangingCount, "#B2");
+                       Assert.AreEqual (1, propChangedCount, "#B3");
+               }
+
+               void SetupNotifyEventsTest (TasqueObject tasqueObject,
+                       string propertyName, string msgPrefix)
+               {
+                       tasqueObject.PropertyChanging += (sender, e) => {
+                               Assert.AreEqual (
+                                       propertyName, e.PropertyName, msgPrefix + "0");
+                               Assert.AreEqual (propChangedCount, propChangingCount++,
+                                                msgPrefix + "1");
+                       };
+                       tasqueObject.PropertyChanged += (sender, e) => {
+                               Assert.AreEqual (
+                                       propertyName, e.PropertyName, msgPrefix + "2");
+                               Assert.AreEqual (propChangingCount, ++propChangedCount,
+                                                msgPrefix + "#3");
+                       };
+               }
+
+               int propChangingCount, propChangedCount;
+               Mock<IRepository> repoMock;
+               TasqueObjectMock tasqueObjectMock;
+
+               public interface IRepo
+               {
+                       string Update (TasqueObject obj, string value);
+               }
+       }
+}
diff --git a/tests/libtasque.Test/libtasque.Test.csproj b/tests/libtasque.Test/libtasque.Test.csproj
new file mode 100644
index 0000000..718413a
--- /dev/null
+++ b/tests/libtasque.Test/libtasque.Test.csproj
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" 
xmlns="http://schemas.microsoft.com/developer/msbuild/2003";>
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>10.0.0</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{8820AFD6-D84B-4A13-A5DE-9EEEC92F3AC3}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <RootNamespace>Tasque</RootNamespace>
+    <AssemblyName>libtasque.Test</AssemblyName>
+    <ReleaseVersion>0.2.0</ReleaseVersion>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>True</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>False</Optimize>
+    <OutputPath>bin\Debug</OutputPath>
+    <DefineConstants>DEBUG;</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <ConsolePause>False</ConsolePause>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="nunit.framework">
+      <Private>False</Private>
+    </Reference>
+    <Reference Include="Moq">
+      <HintPath>..\moq\Moq.dll</HintPath>
+    </Reference>
+    <Reference Include="System.Core" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Core\Impl\NoteTest.cs" />
+  </ItemGroup>
+  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+  <ItemGroup>
+    <ProjectReference Include="..\..\src\libtasque\libtasque.csproj">
+      <Project>{784C9AA8-2B28-400B-8CC4-DCDC48CA37F0}</Project>
+      <Name>libtasque</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <Folder Include="Core\" />
+    <Folder Include="Core\Impl\" />
+    <Folder Include="Data\" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Core\Impl\TaskBackendAttachedTest.cs" />
+    <None Include="Core\Impl\TaskBackendDetachedTest.cs" />
+    <None Include="Core\Impl\TaskTest.cs" />
+    <None Include="Core\Impl\TasqueObjectTest.cs" />
+    <None Include="Core\Impl\TasqueObjectCollectionTest.cs" />
+    <None Include="Core\Impl\TasqueObjectCollectionSharingTest.cs" />
+  </ItemGroup>
+</Project>
\ No newline at end of file
diff --git a/tests/tests.csproj b/tests/tests.csproj
index ec617a4..4c8ab04 100644
--- a/tests/tests.csproj
+++ b/tests/tests.csproj
@@ -12,7 +12,7 @@
     <AssemblyName>Tasque.Tests</AssemblyName>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
-    <ReleaseVersion>0.1.13</ReleaseVersion>
+    <ReleaseVersion>0.2.0</ReleaseVersion>
     <PackageName>tasque</PackageName>
     <TopBuildDir>..</TopBuildDir>
   </PropertyGroup>
@@ -37,9 +37,8 @@
   </ItemGroup>
   <ItemGroup>
     <Compile Include="TaskParserFixture.cs" />
-    <Compile Include="BackendsFixture.cs" />
-    <Compile Include="TasqueTestsSetup.cs" />
     <Compile Include="TaskGroupModelTest.cs" />
+    <Compile Include="DummyBackendTest.cs" />
   </ItemGroup>
   <ItemGroup>
     <ProjectReference Include="..\src\libtasque\libtasque.csproj">
@@ -50,14 +49,6 @@
       <Project>{0F63E512-FD5A-482C-8389-6A0DBE1301CB}</Project>
       <Name>DummyBackend</Name>
     </ProjectReference>
-    <ProjectReference Include="..\src\Addins\Backends\Sqlite\SqliteBackend.csproj">
-      <Project>{CCCC10A5-662D-4788-82D3-25689F3D4D4F}</Project>
-      <Name>SqliteBackend</Name>
-    </ProjectReference>
-    <ProjectReference Include="..\src\Addins\Backends\Rtm\RtmBackend.csproj">
-      <Project>{CC8935CB-342C-4FDA-BAF1-24FA3EB53490}</Project>
-      <Name>RtmBackend</Name>
-    </ProjectReference>
     <ProjectReference Include="..\src\Gtk.Tasque\Gtk.Tasque.csproj">
       <Project>{B19B9840-669D-4984-9772-E1F55193A67F}</Project>
       <Name>Gtk.Tasque</Name>



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