syncevolution/src/backends/evolution/EvolutionCalendarSource.h
Milan Crha edb458dfcb EDS: EDS 3.33.2, libecal 2.0 support
Developed originally by Milan Crha for Fedora, copied and updated
by Patrick Ohly.

From Milan:

There are going to be made huge libecal API changes, as huge as it
deserved a version bump from 1.2 to 2.0, and together with it a small
libebook API changes, most likely being part of the evolution-data-
server 3.33.2 release, which is planned for May 20. More about this can
be found here:
https://mail.gnome.org/archives/desktop-devel-list/2019-April/msg00016.html

Signed-off-by: Patrick Ohly <patrick.ohly@intel.com>
2020-12-05 21:28:08 +01:00

314 lines
10 KiB
C++

/*
* Copyright (C) 2005-2009 Patrick Ohly <patrick.ohly@gmx.de>
* Copyright (C) 2009 Intel Corporation
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) version 3.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#ifndef INCL_EVOLUTIONCALENDARSOURCE
#define INCL_EVOLUTIONCALENDARSOURCE
#include "config.h"
#include "EvolutionSyncSource.h"
#include <syncevo/SmartPtr.h>
#include <boost/noncopyable.hpp>
#ifdef ENABLE_ECAL
#include <syncevo/declarations.h>
#ifdef USE_EDS_CLIENT
SE_GOBJECT_TYPE(ECalClient)
SE_GOBJECT_TYPE(ECalClientView)
#endif
SE_BEGIN_CXX
/**
* Source type independent from ECal / ECalClient to abstract
* the two different enums in the APIs.
*/
typedef enum {
EVOLUTION_CAL_SOURCE_TYPE_EVENTS,
EVOLUTION_CAL_SOURCE_TYPE_TASKS,
EVOLUTION_CAL_SOURCE_TYPE_MEMOS
} EvolutionCalendarSourceType;
inline bool IsCalObjNotFound(const GError *gerror) {
return gerror &&
#ifdef USE_EDS_CLIENT
gerror->domain == E_CAL_CLIENT_ERROR &&
gerror->code == E_CAL_CLIENT_ERROR_OBJECT_NOT_FOUND
#else
gerror->domain == E_CALENDAR_ERROR &&
gerror->code == E_CALENDAR_STATUS_OBJECT_NOT_FOUND
#endif
;
}
/**
* Implements access to Evolution calendars, either
* using the to-do item or events. Change tracking
* is done by looking at the modification time stamp.
* Recurring events and their detached recurrences are
* handled as one item for the main event and one item
* for each detached recurrence.
*/
class EvolutionCalendarSource : public EvolutionSyncSource,
public SyncSourceLogging,
private boost::noncopyable
{
public:
/**
* @param type chooses which kind of calendar data to use:
* EVOLUTION_CAL_SOURCE_TYPE_EVENTS,
* EVOLUTION_CAL_SOURCE_TYPE_TASKS,
* EVOLUTION_CAL_SOURCE_TYPE_MEMOS
*/
EvolutionCalendarSource(EvolutionCalendarSourceType type,
const SyncSourceParams &params);
virtual ~EvolutionCalendarSource() { close(); }
//
// implementation of SyncSource
//
virtual Databases getDatabases();
virtual void open();
virtual bool isEmpty();
virtual void close();
virtual std::string getMimeType() const { return "text/calendar"; }
virtual std::string getMimeVersion() const { return "2.0"; }
void getSynthesisInfo(SynthesisInfo &info,
XMLConfigFragments &fragments)
{
// All EDS calendar storages must suppport UID/RECURRENCE-ID,
// it's part of the API. Therefore we can rely on it.
EvolutionSyncSource::getSynthesisInfo(info, fragments);
info.m_globalIDs = true;
}
/**
* An item is identified in the calendar by
* its UID (unique ID) and RID (recurrence ID).
* The RID may be empty.
*
* This is turned into a SyncML LUID by
* concatenating them: <uid>-rid<rid>.
*/
class ItemID {
public:
ItemID(const string &uid, const string &rid) :
m_uid(uid),
m_rid(rid)
{}
ItemID(const char *uid, const char *rid):
m_uid(uid ? uid : ""),
m_rid(rid ? rid : "")
{}
ItemID(const string &luid);
const string m_uid, m_rid;
string getLUID() const;
static string getLUID(const string &uid, const string &rid);
};
/**
* Extract item ID from calendar item. An icalcomponent must
* refer to the VEVENT/VTODO/VJOURNAL component.
*/
static ItemID getItemID(ECalComponent *ecomp);
static ItemID getItemID(icalcomponent *icomp);
#ifdef HAVE_LIBECAL_2_0
static ItemID getItemID(ICalComponent *icomp);
#endif
/**
* Extract modification string from calendar item.
* @return empty string if no time was available
*/
static string getItemModTime(ECalComponent *ecomp);
static string getItemModTime(icalcomponent *icomp);
#ifdef HAVE_LIBECAL_2_0
static string getItemModTime(ICalComponent *icomp);
#endif
protected:
//
// implementation of TrackingSyncSource callbacks
//
virtual void listAllItems(RevisionMap_t &revisions);
virtual InsertItemResult insertItem(const string &uid, const std::string &item, bool raw);
void readItem(const std::string &luid, std::string &item, bool raw);
virtual void removeItem(const string &uid);
// implementation of SyncSourceLogging callback
virtual std::string getDescription(const string &luid);
protected:
/** valid after open(): the calendar that this source references */
#ifdef USE_EDS_CLIENT
ECalClientCXX m_calendar;
#else
eptr<ECal, GObject> m_calendar;
ECal *(*m_newSystem)(void); /**< e_cal_new_system_calendar, etc. */
#endif
string m_typeName; /**< "calendar", "task list", "memo list" */
EvolutionCalendarSourceType m_type; /**< use events, tasks or memos? */
// Convenience function for source type casting
#ifdef USE_EDS_CLIENT
ECalClientSourceType sourceType() const {
return (ECalClientSourceType)m_type;
}
virtual const char *sourceExtension() const {
return
m_type == EVOLUTION_CAL_SOURCE_TYPE_EVENTS ? E_SOURCE_EXTENSION_CALENDAR :
m_type == EVOLUTION_CAL_SOURCE_TYPE_TASKS ? E_SOURCE_EXTENSION_TASK_LIST :
m_type == EVOLUTION_CAL_SOURCE_TYPE_MEMOS ? E_SOURCE_EXTENSION_MEMO_LIST :
"";
}
virtual ESourceCXX refSystemDB() const {
ESource *(*ref)(ESourceRegistry *) =
m_type == EVOLUTION_CAL_SOURCE_TYPE_EVENTS ? e_source_registry_ref_builtin_calendar :
m_type == EVOLUTION_CAL_SOURCE_TYPE_TASKS ? e_source_registry_ref_builtin_task_list :
m_type == EVOLUTION_CAL_SOURCE_TYPE_MEMOS ? e_source_registry_ref_builtin_memo_list :
nullptr;
return ESourceCXX(ref ? ref(EDSRegistryLoader::getESourceRegistry()) : nullptr, TRANSFER_REF);
}
#else
ECalSourceType sourceType() const {
return (ECalSourceType)m_type;
}
#endif
/**
* retrieve the item with the given id - may throw exception
*
* caller has to free result
*/
#ifdef HAVE_LIBECAL_2_0
ICalComponent *retrieveItem(const ItemID &id);
#else
icalcomponent *retrieveItem(const ItemID &id);
#endif
/** retrieve the item with the given luid as VCALENDAR string - may throw exception */
string retrieveItemAsString(const ItemID &id);
/** returns the type which the ical library uses for our components */
#ifdef HAVE_LIBECAL_2_0
ICalComponentKind getCompType() {
return m_type == EVOLUTION_CAL_SOURCE_TYPE_EVENTS ? I_CAL_VEVENT_COMPONENT :
m_type == EVOLUTION_CAL_SOURCE_TYPE_MEMOS ? I_CAL_VJOURNAL_COMPONENT :
I_CAL_VTODO_COMPONENT;
}
#else
icalcomponent_kind getCompType() {
return m_type == EVOLUTION_CAL_SOURCE_TYPE_EVENTS ? ICAL_VEVENT_COMPONENT :
m_type == EVOLUTION_CAL_SOURCE_TYPE_MEMOS ? ICAL_VJOURNAL_COMPONENT :
ICAL_VTODO_COMPONENT;
}
#endif
#ifndef USE_EDS_CLIENT
/** ECalAuthFunc which calls the authenticate() methods */
static char *eCalAuthFunc(ECal *ecal,
const char *prompt,
const char *key,
gpointer user_data) {
return ((EvolutionCalendarSource *)user_data)->authenticate(prompt, key);
}
/** actual implementation of ECalAuthFunc */
char *authenticate(const char *prompt,
const char *key);
#endif
/**
* Returns the LUID of a calendar item.
*/
string getLUID(ECalComponent *ecomp);
/**
* Extract modification string of an item stored in
* the calendar.
* @return empty string if no time was available
*/
string getItemModTime(const ItemID &id);
/**
* Convert to string in canonical representation.
*/
static string icalTime2Str(const struct icaltimetype &tt);
#ifdef HAVE_LIBECAL_2_0
static string icalTime2Str(const ICalTime *tt);
#endif
/**
* A set of all existing objects. Initialized in the last call to
* listAllItems() and then updated as items get
* added/removed. Used to decide how insertItem() has to be
* implemented without the troublesome querying of the EDS
* backend.
*/
class LUIDs : public map< string, set<string> > {
public:
bool containsUID(const std::string &uid) const { return findUID(uid) != end(); }
const_iterator findUID(const std::string &uid) const { return find(uid); }
bool containsLUID(const ItemID &id) const;
void insertLUID(const ItemID &id);
void eraseLUID(const ItemID &id);
} m_allLUIDs;
/**
* A list of ref-counted smart pointers to icalcomponents.
* The list members can be copied; destroying the last instance
* will destroy the smart pointer, which then calls
* icalcomponent_free().
*/
#ifdef HAVE_LIBECAL_2_0
typedef list< std::shared_ptr< eptr<ICalComponent> > > ICalComps_t;
#else
typedef list< std::shared_ptr< eptr<icalcomponent> > > ICalComps_t;
#endif
/**
* Utility function which extracts all icalcomponents with
* the given UID, stores them in a list and then removes
* them from the calendar. Trying to remove a non-existant
* UID is logged, but not an error. It simply returns an
* empty list.
*
* Relies on m_allLUIDs, but does not update it. The caller must
* ensure that the calendar remains in a consistent state.
*
* @param returnOnlyChildren only return children in list, even if parent is also removed
* @param ignoreNotFound don't throw a STATUS_NOT_FOUND error when deleting fails with
* a NOT_FOUND error
*/
ICalComps_t removeEvents(const string &uid, bool returnOnlyChildren, bool ignoreNotFound = true);
};
SE_END_CXX
#endif // ENABLE_ECAL
#endif // INCL_EVOLUTIONSYNCSOURCE