• Skip to content
  • Skip to link menu
KDE API Documentation - akonadidatasource.cpp Source File (KPeople)
  • KDE Home
  • Contact Us
 

KPeople

  • frameworks
  • kpeople
  • src
  • plugins
  • akonadi
akonadidatasource.cpp
1 /*
2  Copyright (C) 2013 David Edmundson <davidedmundson@kde.org>
3 
4  This library is free software; you can redistribute it and/or
5  modify it under the terms of the GNU Lesser General Public
6  License as published by the Free Software Foundation; either
7  version 2.1 of the License, or (at your option) any later version.
8 
9  This library is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  Lesser General Public License for more details.
13 
14  You should have received a copy of the GNU Lesser General Public
15  License along with this library; if not, write to the Free Software
16  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18 
19 #include "akonadidatasource.h"
20 
21 #include <Akonadi/Item>
22 #include <Akonadi/ItemFetchJob>
23 #include <Akonadi/ItemFetchScope>
24 #include <Akonadi/Collection>
25 #include <Akonadi/CollectionFetchJob>
26 #include <Akonadi/CollectionFetchScope>
27 #include <Akonadi/ServerManager>
28 
29 #include <KPluginFactory>
30 #include <KPluginLoader>
31 
32 #include <QDebug>
33 
34 using namespace Akonadi;
35 
36 class AkonadiAllContacts : public KPeople::AllContactsMonitor
37 {
38  Q_OBJECT
39 public:
40  AkonadiAllContacts();
41  ~AkonadiAllContacts();
42  virtual QMap<QString, AbstractContact::Ptr> contacts();
43 private Q_SLOTS:
44  void onCollectionsFetched(KJob *job);
45  void onItemsFetched(KJob *job);
46  void onItemAdded(const Akonadi::Item &item);
47  void onItemChanged(const Akonadi::Item &item);
48  void onItemRemoved(const Akonadi::Item &item);
49  void onServerStateChanged(Akonadi::ServerManager::State);
50 private:
51  Akonadi::Monitor *m_monitor;
52  QMap<QString, AbstractContact::Ptr> m_contacts;
53  int m_activeFetchJobsCount;
54  bool m_fetchError;
55 };
56 
57 AkonadiAllContacts::AkonadiAllContacts():
58  m_monitor(new Akonadi::Monitor(this)),
59  m_activeFetchJobsCount(0),
60  m_fetchError(false)
61 {
62  connect(Akonadi::ServerManager::self(), SIGNAL(stateChanged(Akonadi::ServerManager::State)), SLOT(onServerStateChanged(Akonadi::ServerManager::State)));
63  onServerStateChanged(Akonadi::ServerManager::state());
64 
65  connect(m_monitor, SIGNAL(itemAdded(Akonadi::Item,Akonadi::Collection)), SLOT(onItemAdded(Akonadi::Item)));
66  connect(m_monitor, SIGNAL(itemChanged(Akonadi::Item,QSet<QByteArray>)), SLOT(onItemChanged(Akonadi::Item)));
67  connect(m_monitor, SIGNAL(itemRemoved(Akonadi::Item)), SLOT(onItemRemoved(Akonadi::Item)));
68 
69  m_monitor->setMimeTypeMonitored("text/directory");
70  m_monitor->itemFetchScope().fetchFullPayload();
71  m_monitor->itemFetchScope().setFetchModificationTime(false);
72 #ifdef HAVE_KDEPIM_ATLEAST_412
73  m_monitor->itemFetchScope().setFetchRemoteIdentification(false);
74 #endif
75 
76  CollectionFetchJob *fetchJob = new CollectionFetchJob(Collection::root(), CollectionFetchJob::Recursive, this);
77  fetchJob->fetchScope().setContentMimeTypes(QStringList() << "text/directory");
78  connect(fetchJob, SIGNAL(finished(KJob*)), SLOT(onCollectionsFetched(KJob*)));
79 }
80 
81 AkonadiAllContacts::~AkonadiAllContacts()
82 {
83 }
84 
85 QMap<QString, AbstractContact::Ptr> AkonadiAllContacts::contacts()
86 {
87  return m_contacts;
88 }
89 
90 QString AkonadiDataSource::sourcePluginId() const
91 {
92  return "akonadi";
93 }
94 
95 void AkonadiAllContacts::onItemAdded(const Item &item)
96 {
97  if (!item.hasPayload<AbstractContact::Ptr>()) {
98  return;
99  }
100  const QString id = item.url().prettyUrl();
101  const AbstractContact::Ptr contact = item.payload<AbstractContact::Ptr>();
102  m_contacts[id] = contact;
103  Q_EMIT contactAdded(item.url().prettyUrl(), contact);
104 }
105 
106 void AkonadiAllContacts::onItemChanged(const Item &item)
107 {
108  if (!item.hasPayload<AbstractContact::Ptr>()) {
109  return;
110  }
111  const QString id = item.url().prettyUrl();
112  const AbstractContact::Ptr contact = item.payload<AbstractContact::Ptr>();
113  m_contacts[id] = contact;
114  Q_EMIT contactChanged(item.url().prettyUrl(), contact);
115 }
116 
117 void AkonadiAllContacts::onItemRemoved(const Item &item)
118 {
119  if (!item.hasPayload<AbstractContact::Ptr>()) {
120  return;
121  }
122  const QString id = item.url().prettyUrl();
123  m_contacts.remove(id);
124  Q_EMIT contactRemoved(id);
125 }
126 
127 //or we could add items as we go along...
128 void AkonadiAllContacts::onItemsFetched(KJob *job)
129 {
130  if (job->error()) {
131  kWarning() << job->errorString();
132  m_fetchError = true;
133  } else {
134  ItemFetchJob *itemFetchJob = qobject_cast<ItemFetchJob *>(job);
135  foreach (const Item &item, itemFetchJob->items()) {
136  onItemAdded(item);
137  }
138  }
139 
140  if (--m_activeFetchJobsCount == 0 && !isInitialFetchComplete()) {
141  emitInitialFetchComplete(true);
142  }
143 }
144 
145 void AkonadiAllContacts::onCollectionsFetched(KJob *job)
146 {
147  if (job->error()) {
148  kWarning() << job->errorString();
149  emitInitialFetchComplete(false);
150  } else {
151  CollectionFetchJob *fetchJob = qobject_cast<CollectionFetchJob *>(job);
152  QList<Collection> contactCollections;
153  foreach (const Collection &collection, fetchJob->collections()) {
154  // Skip virtual collections - we will get contacts linked into virtual
155  // collections from their real parent collections
156  if (collection.isVirtual()) {
157  continue;
158  }
159  if (collection.contentMimeTypes().contains(AbstractContact::Ptr::mimeType())) {
160  ItemFetchJob *itemFetchJob = new ItemFetchJob(collection);
161  itemFetchJob->fetchScope().fetchFullPayload();
162  connect(itemFetchJob, SIGNAL(finished(KJob*)), SLOT(onItemsFetched(KJob*)));
163  ++m_activeFetchJobsCount;
164  }
165  }
166  if (m_activeFetchJobsCount == 0) {
167  emitInitialFetchComplete(true);
168  }
169  }
170  if (m_activeFetchJobsCount == 0 && !isInitialFetchComplete()) {
171  emitInitialFetchComplete(true);
172 
173  }
174 }
175 
176 void AkonadiAllContacts::onServerStateChanged(ServerManager::State state)
177 {
178  //if we're broken tell kpeople we've loaded so kpeople doesn't block
179  if (state == Akonadi::ServerManager::Broken && !isInitialFetchComplete()) {
180  emitInitialFetchComplete(false);
181  qWarning() << "Akonadi failed to load, some metacontact features may not be available";
182  qWarning() << "For more information please load akonadi_console" ;
183  }
184 }
185 
186 class AkonadiContact: public KPeople::ContactMonitor
187 {
188  Q_OBJECT
189 public:
190  AkonadiContact(Akonadi::Monitor *monitor, const QString &contactUri);
191  ~AkonadiContact();
192 private Q_SLOTS:
193  void onContactFetched(KJob *);
194  void onContactChanged(const Akonadi::Item &);
195 private:
196  Akonadi::Monitor *m_monitor;
197  Akonadi::Item m_item;
198 };
199 
200 AkonadiContact::AkonadiContact(Akonadi::Monitor *monitor, const QString &contactUri):
201  ContactMonitor(contactUri),
202  m_monitor(monitor)
203 {
204  //TODO: optimiZation, base class could copy across from the model if the model exists
205  //then we should check if contact is already set to something and avoid the initial fetch
206 
207  //load the contact initially
208  m_item = Item::fromUrl(QUrl(contactUri));
209  ItemFetchJob *itemFetchJob = new ItemFetchJob(m_item);
210  itemFetchJob->fetchScope().fetchFullPayload();
211  connect(itemFetchJob, SIGNAL(finished(KJob*)), SLOT(onContactFetched(KJob*)));
212 
213  //then watch for that item changing
214  m_monitor->setItemMonitored(m_item, true);
215  connect(m_monitor, SIGNAL(itemChanged(Akonadi::Item,QSet<QByteArray>)), SLOT(onContactChanged(Akonadi::Item)));
216 }
217 
218 AkonadiContact::~AkonadiContact()
219 {
220  m_monitor->setItemMonitored(m_item, false);
221 }
222 
223 void AkonadiContact::onContactFetched(KJob *job)
224 {
225  ItemFetchJob *fetchJob = qobject_cast<ItemFetchJob *>(job);
226  if (fetchJob->items().count() && fetchJob->items().first().hasPayload<AbstractContact::Ptr>()) {
227  setContact(fetchJob->items().first().payload<AbstractContact::Ptr>());
228  }
229 }
230 
231 void AkonadiContact::onContactChanged(const Item &item)
232 {
233  if (item != m_item) {
234  return;
235  }
236  if (!item.hasPayload<AbstractContact::Ptr>()) {
237  return;
238  }
239  setContact(item.payload<AbstractContact::Ptr>());
240 }
241 
242 AkonadiDataSource::AkonadiDataSource(QObject *parent, const QVariantList &args):
243  BasePersonsDataSource(parent),
244  m_monitor(new Akonadi::Monitor(this))
245 {
246  Q_UNUSED(args);
247  m_monitor->itemFetchScope().fetchFullPayload();
248  m_monitor->itemFetchScope().setFetchModificationTime(false);
249 #ifdef HAVE_KDEPIM_ATLEAST_412
250  m_monitor->itemFetchScope().setFetchRemoteIdentification(false);
251 #endif
252 }
253 
254 AkonadiDataSource::~AkonadiDataSource()
255 {
256 
257 }
258 
259 KPeople::AllContactsMonitor *AkonadiDataSource::createAllContactsMonitor()
260 {
261  return new AkonadiAllContacts();
262 }
263 
264 KPeople::ContactMonitor *AkonadiDataSource::createContactMonitor(const QString &contactUri)
265 {
266  return new AkonadiContact(m_monitor, contactUri);
267 }
268 
269 K_PLUGIN_FACTORY(AkonadiDataSourceFactory, registerPlugin<AkonadiDataSource>();)
270 K_EXPORT_PLUGIN(AkonadiDataSourceFactory("akonadi_kpeople_plugin"))
271 
272 #include "akonadidatasource.moc"
KPeople::ContactMonitor
This class loads data for a single contact from a datasource.
Definition: contactmonitor.h:42
KPeople::AllContactsMonitor
This class should be subclassed by each datasource and return a list of all contacts that the datasou...
Definition: allcontactsmonitor.h:43
Akonadi
This file is part of the KDE documentation.
Documentation copyright © 1996-2015 The KDE developers.
Generated on Fri Feb 13 2015 15:16:39 by doxygen 1.8.9.1 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KPeople

Skip menu "KPeople"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • File List

Class Picker

Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal