private void OnViewDone (object o, Evolution.ViewDoneArgs args)
		{
			// Now that we're done synching with the original
			// state of the calendar, switch all new changes to
			// Immediate mode
			priority = Scheduler.Priority.Immediate;
		}
		public CalContainer (Evolution.Source source, EvolutionDataServerQueryable queryable, string fingerprint, CalSourceType cal_source_type) 
			: base (source, queryable, fingerprint)
		{
			this.cal_source_type = cal_source_type;
		}
		private void OnObjectsModified (object o, Evolution.ObjectsModifiedArgs args)
		{
			foreach (CalComponent cc in CalUtil.ICalToCalComponentArray (args.Objects.Handle, this.cal_view.Client))
				AddCalComponent (cc);
		}
		private void OnObjectsRemoved (object o, Evolution.ObjectsRemovedArgs args)
		{
			// FIXME: evolution-sharp doesn't know about
			// CalComponentId itself, so we have to workaround
			// this by re-creating the GLib.List with the right
			// type.
			GLib.List id_list = new GLib.List (args.Uids.Handle,
							   typeof (CalComponentId));

			foreach (CalComponentId id in id_list)
				RemoveCalComponent (id.Uid);
		}
		private Indexable ContactToIndexable (Evolution.Contact contact)
		{
			DateTime rev = RevStringToDateTime (contact.Rev);

			Indexable indexable = new Indexable (GetContactUri (contact));
			indexable.Timestamp = rev;
			indexable.HitType = "Contact";

			indexable.AddProperty (Property.NewKeyword ("fixme:client", "evolution"));
			indexable.AddProperty (Property.NewUnsearched ("fixme:source_uid", this.source.Uid));
			indexable.AddProperty (Property.NewUnsearched ("fixme:uid", contact.Id));
						
			indexable.AddProperty (Property.New ("fixme:FileAs", contact.FileAs));
			indexable.AddProperty (Property.New ("fixme:FullName", contact.FullName));
			indexable.AddProperty (Property.New ("fixme:GivenName", contact.GivenName));
			indexable.AddProperty (Property.New ("fixme:FamilyName", contact.FamilyName));
			indexable.AddProperty (Property.New ("fixme:Nickname", contact.Nickname));
			indexable.AddProperty (Property.New ("fixme:AddressLabelHome", contact.AddressLabelHome));
			indexable.AddProperty (Property.New ("fixme:AddressLabelWork", contact.AddressLabelWork));
			indexable.AddProperty (Property.New ("fixme:AddressLabelOther", contact.AddressLabelOther));
			indexable.AddProperty (Property.New ("fixme:AssistantPhone", contact.AssistantPhone));
			indexable.AddProperty (Property.New ("fixme:BusinessPhone", contact.BusinessPhone));
			indexable.AddProperty (Property.New ("fixme:BusinessPhone2", contact.BusinessPhone2));
			indexable.AddProperty (Property.New ("fixme:BusinessFax", contact.BusinessFax));
			indexable.AddProperty (Property.New ("fixme:CallbackPhone", contact.CallbackPhone));
			indexable.AddProperty (Property.New ("fixme:CarPhone", contact.CarPhone));
			indexable.AddProperty (Property.New ("fixme:CompanyPhone", contact.CompanyPhone));
			indexable.AddProperty (Property.New ("fixme:HomePhone", contact.HomePhone));
			indexable.AddProperty (Property.New ("fixme:HomePhone2", contact.HomePhone2));
			indexable.AddProperty (Property.New ("fixme:HomeFax", contact.HomeFax));
			indexable.AddProperty (Property.New ("fixme:IsdnPhone", contact.IsdnPhone));
			indexable.AddProperty (Property.New ("fixme:MobilePhone", contact.MobilePhone));
			indexable.AddProperty (Property.New ("fixme:OtherPhone", contact.OtherPhone));
			indexable.AddProperty (Property.New ("fixme:OtherFax", contact.OtherFax));
			indexable.AddProperty (Property.New ("fixme:Pager", contact.Pager));
			indexable.AddProperty (Property.New ("fixme:PrimaryPhone", contact.PrimaryPhone));
			indexable.AddProperty (Property.New ("fixme:Radio", contact.Radio));
			indexable.AddProperty (Property.New ("fixme:Telex", contact.Telex));
			indexable.AddProperty (Property.NewUnsearched ("fixme:Tty", contact.Tty));
			indexable.AddProperty (Property.NewKeyword ("fixme:Email1", contact.Email1));
			indexable.AddProperty (Property.NewKeyword ("fixme:Email2", contact.Email2));
			indexable.AddProperty (Property.NewKeyword ("fixme:Email3", contact.Email3));
			indexable.AddProperty (Property.NewUnsearched ("fixme:Mailer", contact.Mailer));
			indexable.AddProperty (Property.New ("fixme:Org", contact.Org));
			indexable.AddProperty (Property.New ("fixme:OrgUnit", contact.OrgUnit));
			indexable.AddProperty (Property.New ("fixme:Office", contact.Office));
			indexable.AddProperty (Property.New ("fixme:Title", contact.Title));
			indexable.AddProperty (Property.New ("fixme:Role", contact.Role));
			indexable.AddProperty (Property.New ("fixme:Manager", contact.Manager));
			indexable.AddProperty (Property.New ("fixme:Assistant", contact.Assistant));
			indexable.AddProperty (Property.NewKeyword ("fixme:HomepageUrl", contact.HomepageUrl));
			indexable.AddProperty (Property.NewKeyword ("fixme:BlogUrl", contact.BlogUrl));
			indexable.AddProperty (Property.NewUnsearched ("fixme:Categories", contact.Categories));
			indexable.AddProperty (Property.NewUnsearched ("fixme:Caluri", contact.Caluri));
			indexable.AddProperty (Property.NewUnsearched ("fixme:Icscalendar", contact.Icscalendar));
			indexable.AddProperty (Property.New ("fixme:Spouse", contact.Spouse));
			indexable.AddProperty (Property.New ("fixme:Note", contact.Note));
			
			Evolution.ContactPhoto photo = contact.Photo;

			if (photo.Data != null && photo.Data.Length > 0) {
				string photo_filename = GetPhotoFilename (contact.Id);
				Stream s = new FileStream (photo_filename, FileMode.Create, FileAccess.Write, FileShare.ReadWrite);
				BinaryWriter w = new BinaryWriter (s);
				w.Write (photo.Data);
				w.Close ();
				s.Close ();

				indexable.AddProperty (Property.NewUnsearched ("beagle:Photo", photo_filename));
			}

			foreach (string im in contact.ImAim)
				indexable.AddProperty (Property.NewUnsearched ("fixme:ImAim", im));
			foreach (string im in contact.ImIcq)
				indexable.AddProperty (Property.NewUnsearched ("fixme:ImIcq", im));
			foreach (string im in contact.ImJabber)
				indexable.AddProperty (Property.NewUnsearched ("fixme:ImJabber", im));
			foreach (string im in contact.ImMsn)
				indexable.AddProperty (Property.NewUnsearched ("fixme:ImMsn", im));
			foreach (string im in contact.ImYahoo)
				indexable.AddProperty (Property.NewUnsearched ("fixme:ImYahoo", im));
			foreach (string im in contact.ImGroupwise)
				indexable.AddProperty (Property.NewUnsearched ("fixme:ImGroupwise", im));

			String name = "";
			if (contact.GivenName != null && contact.GivenName != "")
				name = contact.GivenName;
			if (contact.FamilyName != null && contact.FamilyName != "")
				name += " " + contact.FamilyName;
			if (name.Length > 0)
				indexable.AddProperty (Property.New ("fixme:Name", name));
		
			if (contact.Email1 != null)
				indexable.AddProperty (Property.NewKeyword ("fixme:Email",
									    contact.Email1));
			return indexable;
		}
		public BookContainer (Evolution.Source source, EvolutionDataServerQueryable queryable, string fingerprint) : base (source, queryable, fingerprint) { }
		/////////////////////////////////////

		private void AddContact (Evolution.Contact contact)
		{
			Indexable indexable = ContactToIndexable (contact);

			this.queryable.ScheduleIndexable (indexable, this.priority);
		}
		/////////////////////////////////////

		// URI scheme is:
		// contacts:///?source-uid=<value>&contact-uid=<value>
		//
		// The Uri class sucks SO MUCH ASS.  It shits itself
		// on foo:///?bar so we have to insert something in
		// before "?bar".  This is filed as Ximian bug #76146.
		// Hopefully it is just a bug in Mono and not a
		// fundamental problem of the Uri class.  Fortunately
		// Evolution can handle the horribly mangled URIs
		// that come out of it.
		
		private Uri GetContactUri (Evolution.Contact contact) {
			return GetContactUri (contact.Id);
		}
		private void OnSequenceComplete (object o, Evolution.SequenceCompleteArgs args)
		{
			ignore_first_batch = false;

			// Now that we're done synching with the original
			// state of the addressbook, switch all new changes to
			// Immediate mode
			priority = Scheduler.Priority.Immediate;

			Logger.Log.Debug ("Sequence complete!");
		}
		private void OnContactsRemoved (object o, Evolution.ContactsRemovedArgs args)
		{
			if (ignore_first_batch)
				return;

			// FIXME: This is a temporary workaround for the
			// fact that the evolution bindings return a
			// GLib.List with an object type, but there are
			// really strings in there.

			GLib.List id_list = new GLib.List (args.Ids.Handle,
							   typeof (string));

			foreach (string id in id_list)
				RemoveContact (id);
		}
		private void OnContactsChanged (object o, Evolution.ContactsChangedArgs args)
		{
			if (ignore_first_batch)
				return;

			foreach (Evolution.Contact contact in args.Contacts)
				AddContact (contact);
		}