Hacking a way to get contacts data into akonadi: I'm reporting the
[akonadigoogledata.git] / googledataresource.cpp
blobcf73d48ef951025e6338441a602627b1e674dbe6
1 #include "googledataresource.h"
3 #include "settings.h"
4 #include "settingsadaptor.h"
6 #include <QtDBus/QDBusConnection>
7 #include <kabc/addressee.h>
8 #include <kabc/phonenumber.h>
9 #include <kabc/key.h>
10 #include <kabc/errorhandler.h>
11 #include <qstring.h>
12 #include <KWindowSystem>
14 extern "C" {
15 #include <gcalendar.h>
16 #include <gcontact.h>
17 #include <gcal_status.h>
21 /** FIXME: for some reason the 'retrieveItem' functions is not being called.
22 * this makes the entries to lack its contents (name, email, etc).
23 * I should investigate why and fix, for while this is a workaround:
24 * I report the payload in the 'retrieveItems' function.
26 #define ITEM_BUG_WTF
28 using namespace Akonadi;
30 GoogleDataResource::GoogleDataResource( const QString &id )
31 : ResourceBase(id), authenticated(false), dlgConf(NULL)
33 new SettingsAdaptor( Settings::self() );
34 QDBusConnection::sessionBus().registerObject( QLatin1String( "/Settings" ),
35 Settings::self(), QDBusConnection::ExportAdaptors );
38 if (!(gcal = gcal_new(GCONTACT)))
39 exit(1);
40 gcal_set_store_xml(gcal, 1);
43 GoogleDataResource::~GoogleDataResource()
45 gcal_delete(gcal);
46 gcal_cleanup_contacts(&all_contacts);
47 if (dlgConf)
48 delete dlgConf;
51 void GoogleDataResource::retrieveCollections()
53 if (!authenticated) {
54 kError() << "No athentication for Google Contacts available";
55 const QString message = i18nc("@info:status",
56 "No yet authenticated for"
57 " use of Google Contacts");
58 emit error(message);
60 emit status(Broken, message);
61 return;
64 Collection c;
65 c.setParent(Collection::root());
66 c.setRemoteId("google-contacts");
67 c.setName(name());
69 QStringList mimeTypes;
70 mimeTypes << "text/directory";
71 c.setContentMimeTypes(mimeTypes);
73 Collection::List list;
74 list << c;
75 collectionsRetrieved(list);
79 void GoogleDataResource::retrieveItems( const Akonadi::Collection &collection )
81 Q_UNUSED( collection );
83 Item::List items;
84 int result;
86 if (!authenticated) {
87 kError() << "No athentication for Google Contacts available";
88 const QString message = i18nc("@info:status",
89 "No yet authenticated for"
90 " use of Google Contacts");
91 emit error(message);
93 emit status(Broken, message);
94 return;
97 /* Downloading the contacts can be slow and it is blocking. Will
98 * it mess up with akonadi?
100 if ((result = gcal_get_contacts(gcal, &all_contacts)))
101 exit(1);
103 /* Each google entry has a unique ID and edit_url */
104 for (size_t i = 0; i < all_contacts.length; ++i) {
105 Item item(QLatin1String("text/directory"));
106 gcal_contact_t contact = gcal_contact_element(&all_contacts, i);
108 #ifdef ITEM_BUG_WTF
109 KABC::Addressee addressee;
110 KABC::PhoneNumber number;
111 KABC::Key key;
112 QString temp;
114 /* name */
115 temp = gcal_contact_get_title(contact);
116 addressee.setNameFromString(temp);
117 /* email */
118 temp = gcal_contact_get_email(contact);
119 addressee.insertEmail(temp, true);
120 /* edit url: required to do edit/delete */
121 temp = gcal_contact_get_url(contact);
122 addressee.setUid(temp);
123 /* ETag: required by Google Data protocol 2.0 */
124 temp = gcal_contact_get_etag(contact);
125 key.setId(temp);
126 addressee.insertKey(key);
127 /* TODO: telefone, address, etc */
129 item.setPayload<KABC::Addressee>(addressee);
130 #endif
132 item.setRemoteId(gcal_contact_get_id(contact));
135 items << item;
138 itemsRetrieved(items);
141 bool GoogleDataResource::retrieveItem( const Akonadi::Item &item, const QSet<QByteArray> &parts )
143 Q_UNUSED( parts );
144 const QString entry_id = item.remoteId();
145 QString temp;
146 Item newItem(item);
147 gcal_contact_t contact;
148 KABC::Addressee addressee;
149 KABC::PhoneNumber number;
150 KABC::Key key;
152 if (!authenticated) {
153 kError() << "No athentication for Google Contacts available";
154 const QString message = i18nc("@info:status",
155 "No yet authenticated for"
156 " use of Google Contacts");
157 emit error(message);
159 emit status(Broken, message);
160 return false;
164 * And another question, are the requests in the same sequence that
165 * I informed in 'retrieveItems'? For while, I try to locate the entry...
167 for (size_t i = 0; i < all_contacts.length; ++i) {
168 contact = gcal_contact_element(&all_contacts, i);
169 if (entry_id == gcal_contact_get_id(contact)) {
170 /* name */
171 temp = gcal_contact_get_title(contact);
172 addressee.setNameFromString(temp);
174 /* email */
175 temp = gcal_contact_get_email(contact);
176 addressee.insertEmail(temp, true);
178 /* edit url: required to do edit/delete */
179 temp = gcal_contact_get_url(contact);
180 addressee.setUid(temp);
182 /* ETag: required by Google Data protocol 2.0 */
183 temp = gcal_contact_get_etag(contact);
184 key.setId(temp);
185 addressee.insertKey(key);
187 /* TODO: telefone, address, etc */
189 newItem.setPayload<KABC::Addressee>(addressee);
190 return true;
195 return false;
198 void GoogleDataResource::aboutToQuit()
200 // TODO: any cleanup you need to do while there is still an active
201 // event loop. The resource will terminate after this method returns
204 void GoogleDataResource::configure( WId windowId )
206 Q_UNUSED( windowId );
207 char *user, *pass;
208 int result = -1;
209 QByteArray byteUser, bytePass;
211 if (!dlgConf)
212 dlgConf = new dlgGoogleDataConf;
214 if (windowId && dlgConf)
215 KWindowSystem::setMainWindow(dlgConf, windowId);
217 dlgConf->exec();
219 byteUser = dlgConf->eAccount->text().toLocal8Bit();
220 bytePass = dlgConf->ePass->text().toLocal8Bit();
221 user = const_cast<char *>(byteUser.constData());
222 pass = const_cast<char *>(bytePass.constData());
223 if (user)
224 if (pass)
225 result = gcal_get_authentication(gcal, user, pass);
227 /* TODO: in case of authentication error, display an error
228 * message.
230 if (!result)
231 authenticated = true;
233 synchronize();
236 void GoogleDataResource::itemAdded( const Akonadi::Item &item, const Akonadi::Collection &collection )
239 Q_UNUSED(collection);
241 KABC::Addressee addressee;
242 gcal_contact_t contact;
243 QString temp;
244 int result;
246 if (!authenticated) {
247 kError() << "No athentication for Google Contacts available";
248 const QString message = i18nc("@info:status",
249 "No yet authenticated for"
250 " use of Google Contacts");
251 emit error(message);
253 emit status(Broken, message);
254 return;
257 if (item.hasPayload<KABC::Addressee>())
258 addressee = item.payload<KABC::Addressee>();
260 if (!(contact = gcal_contact_new(NULL)))
261 exit(1);
263 temp = addressee.realName();
264 gcal_contact_set_title(contact, const_cast<char *>(qPrintable(temp)));
266 temp = addressee.fullEmail();
267 gcal_contact_set_email(contact, const_cast<char *>(qPrintable(temp)));
269 /* TODO: add remaining fields */
271 if ((result = gcal_add_contact(gcal, contact)))
272 exit(1);
274 gcal_contact_delete(contact);
278 void GoogleDataResource::itemChanged( const Akonadi::Item &item, const QSet<QByteArray> &parts )
280 Q_UNUSED(parts);
282 KABC::Addressee addressee;
283 gcal_contact_t contact;
284 KABC::Key key;
285 QString temp;
286 int result;
288 if (!authenticated) {
289 kError() << "No athentication for Google Contacts available";
290 const QString message = i18nc("@info:status",
291 "No yet authenticated for"
292 " use of Google Contacts");
293 emit error(message);
295 emit status(Broken, message);
296 return;
299 if (item.hasPayload<KABC::Addressee>())
300 addressee = item.payload<KABC::Addressee>();
302 if (!(contact = gcal_contact_new(NULL)))
303 exit(1);
305 temp = addressee.realName();
306 gcal_contact_set_title(contact, const_cast<char *>(qPrintable(temp)));
308 temp = addressee.fullEmail();
309 gcal_contact_set_email(contact, const_cast<char *>(qPrintable(temp)));
311 temp = addressee.uid();
312 gcal_contact_set_id(contact, const_cast<char *>(qPrintable(temp)));
314 /* I suppose that this retrieves the first element in the key list */
315 key = addressee.keys()[0];
316 temp = key.id();
317 gcal_contact_set_etag(contact, const_cast<char *>(qPrintable(temp)));
320 /* TODO: add remaining fields */
322 if ((result = gcal_update_contact(gcal, contact)))
323 exit(1);
326 /* Updates the ETag/url: I suppose that akonadi will save this object */
327 temp = gcal_contact_get_url(contact);
328 addressee.setUid(temp);
330 temp = gcal_contact_get_etag(contact);
331 key.setId(temp);
332 addressee.insertKey(key);
335 gcal_contact_delete(contact);
339 void GoogleDataResource::itemRemoved( const Akonadi::Item &item )
341 KABC::Addressee addressee;
342 gcal_contact_t contact;
343 KABC::Key key;
344 QString temp;
345 int result;
347 if (!authenticated) {
348 kError() << "No athentication for Google Contacts available";
349 const QString message = i18nc("@info:status",
350 "No yet authenticated for"
351 " use of Google Contacts");
352 emit error(message);
354 emit status(Broken, message);
355 return;
358 if (item.hasPayload<KABC::Addressee>())
359 addressee = item.payload<KABC::Addressee>();
361 if (!(contact = gcal_contact_new(NULL)))
362 exit(1);
364 temp = addressee.uid();
365 gcal_contact_set_id(contact, const_cast<char *>(qPrintable(temp)));
367 /* I suppose that this retrieves the first element in the key list */
368 key = addressee.keys()[0];
369 temp = key.id();
370 gcal_contact_set_etag(contact, const_cast<char *>(qPrintable(temp)));
372 if ((result = gcal_erase_contact(gcal, contact)))
373 exit(1);
375 gcal_contact_delete(contact);
379 AKONADI_RESOURCE_MAIN( GoogleDataResource )
381 #include "googledataresource.moc"