Bumped copyright dates for 2013
[barry.git] / desktop / src / EvoSources.cc
blob8cc47b260839df5791b8df2db575aa4bb7dfd7b7
1 ///
2 /// \file EvoSources.cc
3 /// A class that creates a list of Evolution data sources.
4 ///
6 /*
7 Copyright (C) 2011-2013, Net Direct Inc. (http://www.netdirect.ca/)
8 Based on evolution2_sync.h and list_sources.c from evolution opensync plugin
9 by Ian Martin
10 Copyright (C) 2009, Ian Martin, licensed under LGPL 2.1
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
21 See the GNU General Public License in the COPYING file at the
22 root directory of this project for more details.
25 #include "../config.h"
27 #if HAVE_EVOLUTION
30 // Some versions of libical use a ring buffer for the following
31 // functions, for which the library manages memory. Somewhere along
32 // the line, this was fixed so that the application was responsible
33 // for freeing the strings returned by these functions. A warning
34 // was added to the header that would display if HANDLE_LIBICAL_MEMORY
35 // was not defined.
37 // Even newer versions of evolution-data-server, which this plugin
38 // depends on, get rid of some of these functions, while newer
39 // versions of libical add _r variants that implement the
40 // application-free functinality.
42 // Since this plugin does not use these functions, we disable the
43 // warning by defining HANDLE_LIBICAL_MEMORY, then include the
44 // headers.
47 #define HANDLE_LIBICAL_MEMORY 1
49 #include <glib.h>
50 #include <libedataserver/eds-version.h>
52 // For some reason, the evolution-data-server libraries use a floating
53 // point number in the version numbers, which causes trouble during
54 // compiles when compared in preprocessor statements. Define our own
55 // here, only comparing major and minor, since that's all we should need
56 // to care about.
57 #define NON_FLOAT_EDS_CHECK_VERSION(major,minor,micro) \
58 (EDS_MAJOR_VERSION > (major) || \
59 (EDS_MAJOR_VERSION == (major) && EDS_MINOR_VERSION > (minor)) || \
60 (EDS_MAJOR_VERSION == (major) && EDS_MINOR_VERSION == (minor)))
62 #if NON_FLOAT_EDS_CHECK_VERSION(3,6,0)
63 #include <libecal/libecal.h>
64 #include <libebook/libebook.h>
65 #include <libedataserver/libedataserver.h>
67 #include "EvoSources.h"
69 struct EvoFunctions
71 void (*g_type_init)(void);
74 // helper functions
76 void FetchSources(EvoFunctions &funcs, EvoSources::List &list,
77 ESourceRegistry *reg,
78 const gchar *extension_type)
80 GList *sources = e_source_registry_list_sources(reg, extension_type);
82 ESource *source = NULL;
83 GList *s = NULL;
85 for( s = sources; s; s = s->next ) {
86 source = E_SOURCE(s->data);
88 EvoSource sitem;
89 sitem.m_SourceName = e_source_get_display_name(source);
90 sitem.m_SourcePath = e_source_get_uid(source);
92 list.push_back(sitem);
95 g_list_free_full(sources, g_object_unref);
98 void EvoSources::LoadBaseSyms()
100 m_funcs->g_type_init = &g_type_init;
103 bool EvoSources::LoadEbookLib()
105 m_funcs.reset( new EvoFunctions );
106 LoadBaseSyms();
108 m_funcs->g_type_init();
110 GError *gerror = NULL;
111 ESourceRegistry *reg = e_source_registry_new_sync(NULL, &gerror);
113 FetchSources(*m_funcs, m_addressbook, reg,
114 E_SOURCE_EXTENSION_ADDRESS_BOOK);
116 g_object_unref(reg);
118 return true;
121 bool EvoSources::LoadEcalLib()
123 m_funcs.reset( new EvoFunctions );
124 LoadBaseSyms();
126 m_funcs->g_type_init();
128 GError *gerror = NULL;
129 ESourceRegistry *reg = e_source_registry_new_sync(NULL, &gerror);
130 if( !reg ) {
131 m_error_msg = gerror->message;
132 return false;
135 FetchSources(*m_funcs, m_events, reg, E_SOURCE_EXTENSION_CALENDAR);
136 FetchSources(*m_funcs, m_tasks, reg, E_SOURCE_EXTENSION_TASK_LIST);
137 FetchSources(*m_funcs, m_memos, reg, E_SOURCE_EXTENSION_MEMO_LIST);
139 g_object_unref(reg);
141 return true;
146 ///////////////////////////////////////////////////////////////////////////////
147 #else // EDS_CHECK_VERSION(3,6,0)
148 ///////////////////////////////////////////////////////////////////////////////
151 #include <libecal/e-cal.h>
152 #include <libebook/e-book.h>
153 #include <libedataserver/e-data-server-util.h>
155 #include "EvoSources.h"
157 struct EvoFunctions
159 void (*g_type_init)(void);
161 gboolean (*e_book_get_addressbooks)(ESourceList**, GError **);
163 gboolean (*e_cal_get_sources)(ESourceList **, ECalSourceType, GError **);
165 GSList* (*e_source_list_peek_groups)(ESourceList *);
166 GSList* (*e_source_group_peek_sources)(ESourceGroup *);
167 const gchar* (*e_source_group_peek_name)(ESourceGroup *);
168 const gchar* (*e_source_peek_name)(ESource *);
169 gchar* (*e_source_get_uri)(ESource *);
172 // helper functions
174 void FetchSources(EvoFunctions &funcs, EvoSources::List &list,
175 ESourceList *sources)
177 GSList *g = NULL;
178 for( g = funcs.e_source_list_peek_groups(sources); g; g = g->next ) {
179 ESourceGroup *group = (ESourceGroup*) g->data;
181 GSList *s = NULL;
182 for( s = funcs.e_source_group_peek_sources(group); s; s = s->next ) {
183 EvoSource sitem;
184 ESource *source = (ESource*) s->data;
186 sitem.m_GroupName = funcs.e_source_group_peek_name(group);
187 sitem.m_SourceName = funcs.e_source_peek_name(source);
188 sitem.m_SourcePath = funcs.e_source_get_uri(source);
190 list.push_back(sitem);
195 void FetchAddressBooks(EvoFunctions &funcs, EvoSources::List &list)
197 ESourceList *sources = NULL;
198 if( funcs.e_book_get_addressbooks(&sources, NULL) ) {
199 FetchSources(funcs, list, sources);
203 void FetchCalendars(EvoFunctions &funcs, EvoSources::List &list,
204 ECalSourceType source_type)
206 ESourceList *sources = NULL;
207 if( funcs.e_cal_get_sources(&sources, source_type, NULL) ) {
208 FetchSources(funcs, list, sources);
212 void EvoSources::LoadBaseSyms()
214 // Ideally, these functions would be loaded dynamically,
215 // but there are two problems with that, which need to be
216 // cracked first:
218 // - the glib major version numbers, according to the .so
219 // files, are not consistent between distros
220 // - when used dynamically, in a program that is not otherwise
221 // linked to glib, it can segfault... and it seems to get
222 // funky somewhere inside glib itself... so I'm guessing that
223 // the library is not being initialized properly :-(
225 // All this means that general compilations of barrydesktop will
226 // need evolution-data-server and friends linked in. It is possible
227 // to compile without, but then you risk getting a weak auto-detection
228 // of data sources in newer versions of evolution. If your data
229 // sources are located in paths like this:
231 // file:///home/cdfrey/.evolution/addressbook/local/system
233 // then it is safe to disable evolution for the barrydesktop compile.
234 // Otherwise, if your version of evolution uses funkier names, or
235 // uses local:system, or puts its files under ~/.config, then
236 // build with evolution and link against it.
238 // Note that if you do not have any OpenSync libraries installed,
239 // then you don't need this evolution source detection at all, and
240 // you can safely disable evolution for the barrydesktop compile too,
241 // since the desktop GUI will not allow the user to even enter the
242 // sync screen without OpenSync.
245 m_funcs->g_type_init = &g_type_init;
246 m_funcs->e_source_list_peek_groups = &e_source_list_peek_groups;
247 m_funcs->e_source_group_peek_sources = &e_source_group_peek_sources;
248 m_funcs->e_source_group_peek_name = &e_source_group_peek_name;
249 m_funcs->e_source_peek_name = &e_source_peek_name;
250 m_funcs->e_source_get_uri = &e_source_get_uri;
252 m_funcs->e_book_get_addressbooks = &e_book_get_addressbooks;
253 m_funcs->e_cal_get_sources = &e_cal_get_sources;
256 bool EvoSources::LoadEbookLib()
258 m_funcs.reset( new EvoFunctions );
259 LoadBaseSyms();
261 m_funcs->g_type_init();
263 FetchAddressBooks(*m_funcs, m_addressbook);
265 return true;
268 bool EvoSources::LoadEcalLib()
270 m_funcs.reset( new EvoFunctions );
271 LoadBaseSyms();
273 m_funcs->g_type_init();
275 FetchCalendars(*m_funcs, m_events, E_CAL_SOURCE_TYPE_EVENT);
276 FetchCalendars(*m_funcs, m_tasks, E_CAL_SOURCE_TYPE_TODO);
277 FetchCalendars(*m_funcs, m_memos, E_CAL_SOURCE_TYPE_JOURNAL);
279 return true;
282 #endif // EDS_CHECK_VERSION
284 void EvoSources::Detect()
286 Clear();
288 if( LoadEbookLib() && LoadEcalLib() ) {
289 // done!
290 m_supported = true;
292 else {
293 Clear();
294 GuessPaths();
295 m_supported = false;
299 bool EvoSources::IsSupported() const
301 return m_supported;
307 /////////////////////////////////////////////////////////////////////////////
308 #else // HAVE_EVOLUTION
309 /////////////////////////////////////////////////////////////////////////////
314 // No Evolution data libraries available
316 #include "EvoSources.h"
317 #include <string>
319 // helper functions
321 void EvoSources::Detect()
323 GuessPaths();
326 bool EvoSources::IsSupported() const
328 return false;
333 /////////////////////////////////////////////////////////////////////////////
334 #endif // HAVE_EVOLUTION
335 /////////////////////////////////////////////////////////////////////////////
338 #include <sys/types.h>
339 #include <sys/stat.h>
340 #include <unistd.h>
341 #include <pwd.h>
343 using namespace std;
345 bool EvoSources::PathExists(const std::string &path)
347 struct stat s;
348 if( stat(path.c_str(), &s) == 0 ) {
349 if( S_ISDIR(s.st_mode) ) {
350 return true;
353 return false;
356 void SetIfExists(EvoSources::List &list,
357 const std::string &group,
358 const std::string &name,
359 const std::string &dir)
361 if( EvoSources::PathExists(dir) ) {
362 EvoSource sitem;
364 sitem.m_GroupName = group;
365 sitem.m_SourceName = name;
366 sitem.m_SourcePath = "file://" + dir;
368 list.push_back(sitem);
372 EvoSources::EvoSources()
374 Detect();
377 void EvoSources::GuessPaths()
379 struct passwd *pw = getpwuid(getuid());
380 if( !pw )
381 return;
383 string base = pw->pw_dir;
384 base += "/.evolution/";
386 string tail = "/local/system";
388 SetIfExists(m_addressbook, "Autodetect", "Addressbook", base + "addressbook" + tail);
389 SetIfExists(m_events, "Autodetect", "Events", base + "calendar" + tail);
390 SetIfExists(m_tasks, "Autodetect", "Tasks", base + "tasks" + tail);
391 SetIfExists(m_memos, "Autodetect", "Memos", base + "memos" + tail);
394 void EvoSources::Clear()
396 m_addressbook.clear();
397 m_events.clear();
398 m_tasks.clear();
399 m_memos.clear();
402 bool EvoSources::IsEmpty() const
404 return m_addressbook.empty() &&
405 m_events.empty() &&
406 m_tasks.empty() &&
407 m_memos.empty();
410 bool EvoSources::IsDefaultable() const
412 return
413 // first three are required
414 m_addressbook.size() && m_addressbook[0].m_SourcePath.size() &&
415 m_events.size() && m_events[0].m_SourcePath.size() &&
416 m_tasks.size() && m_tasks[0].m_SourcePath.size() &&
418 // and all lists must not have more than 1 item
419 m_addressbook.size() <= 1 &&
420 m_events.size() <= 1 &&
421 m_tasks.size() <= 1 &&
422 m_memos.size() <= 1;