desktop: added timezone list to CalendarEditDlg
[barry.git] / desktop / src / EvoSources.cc
blobe3b361e9792a936e26f96a04f82a040ba33ec0dc
1 ///
2 /// \file EvoSources.cc
3 /// A class that creates a list of Evolution data sources.
4 ///
6 /*
7 Copyright (C) 2011-2012, 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
48 #include <glib.h>
49 #include <libecal/e-cal.h>
50 #include <libebook/e-book.h>
51 #include <libedataserver/e-data-server-util.h>
53 #include "EvoSources.h"
55 struct EvoFunctions
57 void (*g_type_init)(void);
59 gboolean (*e_book_get_addressbooks)(ESourceList**, GError **);
61 gboolean (*e_cal_get_sources)(ESourceList **, ECalSourceType, GError **);
63 GSList* (*e_source_list_peek_groups)(ESourceList *);
64 GSList* (*e_source_group_peek_sources)(ESourceGroup *);
65 const gchar* (*e_source_group_peek_name)(ESourceGroup *);
66 const gchar* (*e_source_peek_name)(ESource *);
67 gchar* (*e_source_get_uri)(ESource *);
70 // helper functions
72 void FetchSources(EvoFunctions &funcs, EvoSources::List &list,
73 ESourceList *sources)
75 GSList *g = NULL;
76 for( g = funcs.e_source_list_peek_groups(sources); g; g = g->next ) {
77 ESourceGroup *group = (ESourceGroup*) g->data;
79 GSList *s = NULL;
80 for( s = funcs.e_source_group_peek_sources(group); s; s = s->next ) {
81 EvoSource sitem;
82 ESource *source = (ESource*) s->data;
84 sitem.m_GroupName = funcs.e_source_group_peek_name(group);
85 sitem.m_SourceName = funcs.e_source_peek_name(source);
86 sitem.m_SourcePath = funcs.e_source_get_uri(source);
88 list.push_back(sitem);
93 void FetchCalendars(EvoFunctions &funcs, EvoSources::List &list,
94 ECalSourceType source_type)
96 ESourceList *sources = NULL;
97 if( funcs.e_cal_get_sources(&sources, source_type, NULL) ) {
98 FetchSources(funcs, list, sources);
102 void EvoSources::LoadBaseSyms()
104 // Ideally, these functions would be loaded dynamically,
105 // but there are two problems with that, which need to be
106 // cracked first:
108 // - the glib major version numbers, according to the .so
109 // files, are not consistent between distros
110 // - when used dynamically, in a program that is not otherwise
111 // linked to glib, it can segfault... and it seems to get
112 // funky somewhere inside glib itself... so I'm guessing that
113 // the library is not being initialized properly :-(
115 // All this means that general compilations of barrydesktop will
116 // need evolution-data-server and friends linked in. It is possible
117 // to compile without, but then you risk getting a weak auto-detection
118 // of data sources in newer versions of evolution. If your data
119 // sources are located in paths like this:
121 // file:///home/cdfrey/.evolution/addressbook/local/system
123 // then it is safe to disable evolution for the barrydesktop compile.
124 // Otherwise, if your version of evolution uses funkier names, or
125 // uses local:system, or puts its files under ~/.config, then
126 // build with evolution and link against it.
129 LoadSym(m_funcs->g_type_init, "g_type_init");
130 LoadSym(m_funcs->e_source_list_peek_groups,
131 "e_source_list_peek_groups");
132 LoadSym(m_funcs->e_source_group_peek_sources,
133 "e_source_group_peek_sources");
134 LoadSym(m_funcs->e_source_group_peek_name,
135 "e_source_group_peek_name");
136 LoadSym(m_funcs->e_source_peek_name, "e_source_peek_name");
137 LoadSym(m_funcs->e_source_get_uri, "e_source_get_uri");
139 m_funcs->g_type_init = &g_type_init;
140 m_funcs->e_source_list_peek_groups = &e_source_list_peek_groups;
141 m_funcs->e_source_group_peek_sources = &e_source_group_peek_sources;
142 m_funcs->e_source_group_peek_name = &e_source_group_peek_name;
143 m_funcs->e_source_peek_name = &e_source_peek_name;
144 m_funcs->e_source_get_uri = &e_source_get_uri;
146 m_funcs->e_book_get_addressbooks = &e_book_get_addressbooks;
147 m_funcs->e_cal_get_sources = &e_cal_get_sources;
150 bool EvoSources::LoadEbookLib()
152 // try {
153 m_funcs.reset( new EvoFunctions );
154 // if( !Open("libebook-1.2.so.9") )
155 // return false;
156 LoadBaseSyms();
157 // LoadSym(m_funcs->e_book_get_addressbooks, "e_book_get_addressbooks");
159 m_funcs->g_type_init();
161 ESourceList *sources = NULL;
162 if (m_funcs->e_book_get_addressbooks(&sources, NULL)) {
163 FetchSources(*m_funcs, m_addressbook, sources);
166 return true;
167 // }
168 // catch( DlError & ) {
169 // return false;
170 // }
173 bool EvoSources::LoadEcalLib()
175 // try {
176 m_funcs.reset( new EvoFunctions );
177 // if( !Open("libecal-1.2.so.7") )
178 // return false;
179 LoadBaseSyms();
180 // LoadSym(m_funcs->e_cal_get_sources, "e_cal_get_sources");
182 m_funcs->g_type_init();
184 FetchCalendars(*m_funcs, m_events, E_CAL_SOURCE_TYPE_EVENT);
185 FetchCalendars(*m_funcs, m_tasks, E_CAL_SOURCE_TYPE_TODO);
186 FetchCalendars(*m_funcs, m_memos, E_CAL_SOURCE_TYPE_JOURNAL);
188 return true;
189 // }
190 // catch( DlError & ) {
191 // return false;
192 // }
195 void EvoSources::Detect()
197 Clear();
199 if( LoadEbookLib() && LoadEcalLib() ) {
200 // done!
201 m_supported = true;
203 else {
204 Clear();
205 GuessPaths();
206 m_supported = false;
209 // shutdown to unload symbols
210 // Shutdown();
213 bool EvoSources::IsSupported() const
215 return m_supported;
218 #else // HAVE_EVOLUTION
220 // No Evolution data libraries available
222 #include "EvoSources.h"
223 #include <string>
225 // helper functions
227 void EvoSources::Detect()
229 GuessPaths();
232 bool EvoSources::IsSupported() const
234 return false;
237 #endif // HAVE_EVOLUTION
240 #include <sys/types.h>
241 #include <sys/stat.h>
242 #include <unistd.h>
243 #include <pwd.h>
245 using namespace std;
247 bool EvoSources::PathExists(const std::string &path)
249 struct stat s;
250 if( stat(path.c_str(), &s) == 0 ) {
251 if( S_ISDIR(s.st_mode) ) {
252 return true;
255 return false;
258 void SetIfExists(EvoSources::List &list,
259 const std::string &group,
260 const std::string &name,
261 const std::string &dir)
263 if( EvoSources::PathExists(dir) ) {
264 EvoSource sitem;
266 sitem.m_GroupName = group;
267 sitem.m_SourceName = name;
268 sitem.m_SourcePath = "file://" + dir;
270 list.push_back(sitem);
274 EvoSources::EvoSources()
276 Detect();
279 void EvoSources::GuessPaths()
281 struct passwd *pw = getpwuid(getuid());
282 if( !pw )
283 return;
285 string base = pw->pw_dir;
286 base += "/.evolution/";
288 string tail = "/local/system";
290 SetIfExists(m_addressbook, "Autodetect", "Addressbook", base + "addressbook" + tail);
291 SetIfExists(m_events, "Autodetect", "Events", base + "calendar" + tail);
292 SetIfExists(m_tasks, "Autodetect", "Tasks", base + "tasks" + tail);
293 SetIfExists(m_memos, "Autodetect", "Memos", base + "memos" + tail);
296 void EvoSources::Clear()
298 m_addressbook.clear();
299 m_events.clear();
300 m_tasks.clear();
301 m_memos.clear();
304 bool EvoSources::IsEmpty() const
306 return m_addressbook.empty() &&
307 m_events.empty() &&
308 m_tasks.empty() &&
309 m_memos.empty();
312 bool EvoSources::IsDefaultable() const
314 return
315 // first three are required
316 m_addressbook.size() && m_addressbook[0].m_SourcePath.size() &&
317 m_events.size() && m_events[0].m_SourcePath.size() &&
318 m_tasks.size() && m_tasks[0].m_SourcePath.size() &&
320 // and all lists must not have more than 1 item
321 m_addressbook.size() <= 1 &&
322 m_events.size() <= 1 &&
323 m_tasks.size() <= 1 &&
324 m_memos.size() <= 1;