1 /*
2  kopetedbusinterface.h - Kopete D-Bus interface
3 
4  Copyright (c) 2007      by Michaël Larouche      <larouche@kde.org>
5  Copyright (c) 2007         Will Stephenson       <wstephenson@kde.org>
6 
7  Kopete    (c) 2002-2007 by the Kopete developers <kopete-devel@kde.org>
8 
9  *************************************************************************
10  *                                                                       *
11  * This library is free software; you can redistribute it and/or         *
12  * modify it under the terms of the GNU Lesser General Public            *
13  * License as published by the Free Software Foundation; either          *
14  * version 2 of the License, or (at your option) any later version.      *
15  *                                                                       *
16  *************************************************************************
17  */
18 #include "kopetedbusinterface.h"
19 #include "kopetedbusinterface_p.h"
20 
21 // Qt includes
22 #include <QStringList>
23 #include <QList>
24 
25 // KDE includes
26 #include <QUrl>
27 #include <kplugininfo.h>
28 
29 // Kopete includes
30 #include <kopetecontactlist.h>
31 #include <kopetemetacontact.h>
32 #include <kopetecontact.h>
33 #include <kopeteidentity.h>
34 #include <kopeteidentitymanager.h>
35 #include <kopeteavatarmanager.h>
36 #include <kopeteaccount.h>
37 #include <kopeteaccountmanager.h>
38 #include <kopeteonlinestatus.h>
39 #include <kopetemessage.h>
40 #include <kopetechatsession.h>
41 #include <kopetegroup.h>
42 #include <kopetepluginmanager.h>
43 #include <kopetepicture.h>
44 #include <kopeteviewmanager.h>
45 #include <kopetemessageevent.h>
46 
47 // Local includes
48 #include "kopeteadaptor.h"
49 
KopeteDBusInterface(QObject * parent)50 KopeteDBusInterface::KopeteDBusInterface(QObject *parent)
51     : QObject(parent)
52     , d(new KopeteDBusInterfacePrivate())
53 {
54     setObjectName(QStringLiteral("KopeteDBusInterface"));
55     new KopeteAdaptor(this);
56     QDBusConnection::sessionBus().registerObject(QStringLiteral("/Kopete"), this);
57 
58     QObject::connect(d, SIGNAL(contactChanged(QString)), this, SIGNAL(contactChanged(QString)));
59 }
60 
~KopeteDBusInterface()61 KopeteDBusInterface::~KopeteDBusInterface()
62 {
63 }
64 
protocols() const65 QStringList KopeteDBusInterface::protocols() const
66 {
67     QStringList list;
68     foreach (KPluginInfo p, Kopete::PluginManager::self()->availablePlugins("Protocols")) {
69         list << p.name();
70     }
71     return list;
72 }
73 
contacts() const74 QStringList KopeteDBusInterface::contacts() const
75 {
76     return d->listContact(Kopete::ContactList::self()->metaContacts());
77 }
78 
contactsByFilter(const QString & filter) const79 QStringList KopeteDBusInterface::contactsByFilter(const QString &filter) const
80 {
81     QList<Kopete::MetaContact *> completeList
82         = Kopete::ContactList::self()->metaContacts();
83     QList<Kopete::MetaContact *> filteredList;
84 
85     Kopete::MetaContact *contact;
86 
87     if (filter.toLower() == QLatin1String("online")) {
88         // "online" returns contacts that are not offline, which means that
89         // those being away, busy etc. are included as well.
90         foreach (contact, completeList) {
91             if (contact->isOnline()) {
92                 filteredList << contact;
93             }
94         }
95     } else if (filter.toLower() == QLatin1String("reachable")) {
96         foreach (contact, completeList) {
97             if (contact->isReachable()) {
98                 filteredList << contact;
99             }
100         }
101     } else if (filter.toLower() == QLatin1String("filecapable")) {
102         foreach (contact, completeList) {
103             if (contact->canAcceptFiles()) {
104                 filteredList << contact;
105             }
106         }
107     } else if (filter.toLower() == QLatin1String("away")) {
108         foreach (contact, completeList) {
109             if (contact->status() == Kopete::OnlineStatus::Away) {
110                 filteredList << contact;
111             }
112         }
113     } else if (filter.toLower() == QLatin1String("busy")) {
114         foreach (contact, completeList) {
115             if (contact->status() == Kopete::OnlineStatus::Busy) {
116                 filteredList << contact;
117             }
118         }
119     }
120 
121     return d->listContact(filteredList);
122 }
123 
setIdentityNickName(const QString & nickName,const QString & identityId)124 void KopeteDBusInterface::setIdentityNickName(const QString &nickName, const QString &identityId)
125 {
126     Kopete::Identity *identity = 0;
127 
128     if (identityId.isEmpty()) {
129         identity = Kopete::IdentityManager::self()->defaultIdentity();
130     } else {
131         identity = Kopete::IdentityManager::self()->findIdentity(identityId);
132     }
133 
134     if (identity) {
135         identity->setProperty(Kopete::Global::Properties::self()->nickName(),
136                               nickName);
137     }
138 }
139 
setIdentityAvatar(const QString & avatarUrl,const QString & identityId)140 void KopeteDBusInterface::setIdentityAvatar(const QString &avatarUrl, const QString &identityId)
141 {
142     Kopete::Identity *identity = 0;
143 
144     if (identityId.isEmpty()) {
145         identity = Kopete::IdentityManager::self()->defaultIdentity();
146     } else {
147         identity = Kopete::IdentityManager::self()->findIdentity(identityId);
148     }
149 
150     if (identity) {
151         // Add the avatar using AvatarManager
152         Kopete::AvatarManager::AvatarEntry avatarEntry;
153         avatarEntry.name = QStringLiteral("D-Bus Avatar");
154         avatarEntry.path = QUrl(avatarUrl).path();
155         avatarEntry.category = Kopete::AvatarManager::User;
156 
157         avatarEntry = Kopete::AvatarManager::self()->add(avatarEntry);
158 
159         identity->setProperty(Kopete::Global::Properties::self()->photo(),
160                               avatarEntry.path);
161     }
162 }
163 
setIdentityOnlineStatus(const QString & status,const QString & message,const QString & identityId)164 void KopeteDBusInterface::setIdentityOnlineStatus(const QString &status, const QString &message, const QString &identityId)
165 {
166     Kopete::Identity *identity = 0;
167 
168     if (identityId.isEmpty()) {
169         identity = Kopete::IdentityManager::self()->defaultIdentity();
170     } else {
171         identity = Kopete::IdentityManager::self()->findIdentity(identityId);
172     }
173 
174     if (identity) {
175         identity->setOnlineStatus(d->status2Value(status), message);
176     }
177 }
178 
identities() const179 QStringList KopeteDBusInterface::identities() const
180 {
181     QStringList result;
182 
183     foreach (Kopete::Identity *identity, Kopete::IdentityManager::self()->identities()) {
184         result << identity->id();
185     }
186 
187     return result;
188 }
189 
labelForIdentity(const QString & id) const190 QString KopeteDBusInterface::labelForIdentity(const QString &id) const
191 {
192     Kopete::Identity *identity
193         = Kopete::IdentityManager::self()->findIdentity(id);
194     if (identity) {
195         return identity->label();
196     } else {
197         return QString();
198     }
199 }
200 
accounts() const201 QStringList KopeteDBusInterface::accounts() const
202 {
203     QStringList result;
204 
205     foreach (Kopete::Account *account, Kopete::AccountManager::self()->accounts()) {
206         result << account->accountId();
207     }
208 
209     return result;
210 }
211 
connectAll()212 void KopeteDBusInterface::connectAll()
213 {
214     Kopete::AccountManager::self()->setOnlineStatus(
215         Kopete::OnlineStatusManager::Online, QString(),
216         Kopete::AccountManager::ConnectIfOffline);
217 }
218 
disconnectAll()219 void KopeteDBusInterface::disconnectAll()
220 {
221     Kopete::AccountManager::self()->setOnlineStatus(
222         Kopete::OnlineStatusManager::Offline);
223 }
224 
suspend()225 void KopeteDBusInterface::suspend()
226 {
227     Kopete::AccountManager::self()->suspend();
228 }
229 
resume()230 void KopeteDBusInterface::resume()
231 {
232     Kopete::AccountManager::self()->resume();
233 }
234 
setOnlineStatus(const QString & status,const QString & message)235 void KopeteDBusInterface::setOnlineStatus(const QString &status, const QString &message)
236 {
237     Kopete::AccountManager::self()->setOnlineStatus(d->status2Value(status),
238                                                     message);
239 }
240 
setStatusMessage(const QString & message)241 void KopeteDBusInterface::setStatusMessage(const QString &message)
242 {
243     Kopete::AccountManager::self()->setStatusMessage(message);
244 }
245 
sendMessage(const QString & contactId,const QString & message)246 void KopeteDBusInterface::sendMessage(const QString &contactId, const QString &message)
247 {
248     Kopete::MetaContact *destMetaContact = d->findContact(contactId);
249     if (destMetaContact && destMetaContact->isReachable()) {
250         Kopete::Contact *destContact = destMetaContact->execute();
251         if (destContact) {
252             Kopete::Message newMessage(destContact->account()->myself(),
253                                        destContact);
254             newMessage.setPlainBody(message);
255             newMessage.setDirection(Kopete::Message::Outbound);
256 
257             destContact->manager(Kopete::Contact::CanCreate)->sendMessage(
258                 newMessage);
259         }
260     }
261 }
262 
openChat(const QString & contactId)263 void KopeteDBusInterface::openChat(const QString &contactId)
264 {
265     Kopete::MetaContact *contact = d->findContact(contactId);
266     if (contact && contact->isReachable()) {
267         Kopete::Contact *preferredContact = contact->preferredContact();
268         if (preferredContact && preferredContact->account()
269             && preferredContact != preferredContact->account()->myself()) {
270             contact->execute();
271         }
272     }
273 }
274 
getDisplayName(const QString & contactId)275 QString KopeteDBusInterface::getDisplayName(const QString &contactId)
276 {
277     Kopete::MetaContact *contact = d->findContact(contactId);
278     if (contact) {
279         return contact->displayName();
280     } else {
281         return QLatin1String("");
282     }
283 }
284 
isContactOnline(const QString & contactId)285 bool KopeteDBusInterface::isContactOnline(const QString &contactId)
286 {
287     Kopete::MetaContact *contact = d->findContact(contactId);
288     if (contact) {
289         return contact->isOnline();
290     } else {
291         return false;
292     }
293 }
294 
addContact(const QString & protocolName,const QString & accountId,const QString & contactId,const QString & displayName,const QString & groupName)295 bool KopeteDBusInterface::addContact(const QString &protocolName, const QString &accountId, const QString &contactId, const QString &displayName, const QString &groupName)
296 {
297     QString protocolId = protocolName;
298     if (!protocolName.contains(QLatin1String("Protocol"))) {
299         protocolId += QLatin1String("Protocol");
300     }
301 
302     // Find the account using the given parameters on D-Bus
303     Kopete::Account *account = Kopete::AccountManager::self()->findAccount(
304         protocolId, accountId);
305 
306     if (account) {
307         QString contactName;
308         Kopete::Group *realGroup = 0;
309 
310         if (displayName.isEmpty()) {
311             contactName = contactId;
312         } else {
313             contactName = displayName;
314         }
315 
316         if (!groupName.isEmpty()) {
317             realGroup = Kopete::ContactList::self()->findGroup(groupName);
318         }
319 
320         account->addContact(contactId, contactName, realGroup,
321                             Kopete::Account::DontChangeKABC);
322 
323         return true;
324     }
325 
326     return false;
327 }
328 
sendFile(const QString & contactId,const QString & fileUrl)329 void KopeteDBusInterface::sendFile(const QString &contactId, const QString &fileUrl)
330 {
331     Kopete::MetaContact *destMetaContact = d->findContact(contactId);
332     if (destMetaContact && destMetaContact->isReachable()) {
333         Kopete::Contact *destContact = destMetaContact->execute();
334         if (destContact && destContact->isFileCapable()) {
335             destContact->sendFile(QUrl::fromLocalFile(fileUrl));
336         }
337     }
338 }
339 
isConnected(const QString & protocolName,const QString & accountId)340 bool KopeteDBusInterface::isConnected(const QString &protocolName, const QString &accountId)
341 {
342     QString protocolId = protocolName;
343     if (!protocolName.contains(QLatin1String("Protocol"))) {
344         protocolId += QLatin1String("Protocol");
345     }
346 
347     Kopete::Account *account = Kopete::AccountManager::self()->findAccount(
348         protocolId, accountId);
349     return account ? account->isConnected() : false;
350 }
351 
connect(const QString & protocolName,const QString & accountId)352 void KopeteDBusInterface::connect(const QString &protocolName, const QString &accountId)
353 {
354     QString protocolId = protocolName;
355     if (!protocolName.contains(QLatin1String("Protocol"))) {
356         protocolId += QLatin1String("Protocol");
357     }
358 
359     Kopete::Account *account = Kopete::AccountManager::self()->findAccount(
360         protocolId, accountId);
361     if (account) {
362         account->connect();
363     }
364 }
365 
disconnect(const QString & protocolName,const QString & accountId)366 void KopeteDBusInterface::disconnect(const QString &protocolName, const QString &accountId)
367 {
368     QString protocolId = protocolName;
369     if (!protocolName.contains(QLatin1String("Protocol"))) {
370         protocolId += QLatin1String("Protocol");
371     }
372 
373     Kopete::Account *account = Kopete::AccountManager::self()->findAccount(
374         protocolId, accountId);
375     if (account) {
376         account->disconnect();
377     }
378 }
379 
contactProperties(const QString & contactId)380 QVariantMap KopeteDBusInterface::contactProperties(const QString &contactId)
381 {
382     QVariantMap properties;
383     Kopete::MetaContact *contact = d->findContact(contactId);
384 
385     if (contact) {
386         properties[QStringLiteral("status")] = Kopete::OnlineStatus::statusTypeToString(
387             contact->status());
388         properties[QStringLiteral("message_reachable")] = contact->isReachable();
389         properties[QStringLiteral("file_reachable")] = contact->canAcceptFiles();
390         properties[QStringLiteral("display_name")] = contact->displayName();
391         properties[QStringLiteral("id")] = contact->metaContactId().toString();
392         if (contact->photoSource() == Kopete::MetaContact::SourceCustom) {
393             properties[QStringLiteral("picture")] = contact->customPhoto().toDisplayString();
394         } else {
395             properties[QStringLiteral("picture")] = contact->picture().path();
396         }
397         properties[QStringLiteral("idle_time")] = qulonglong(contact->idleTime());
398         if (contact->preferredContact()) {
399             /** @todo: export status message title as well or merge both? */
400             properties[QStringLiteral("status_message")]
401                 = contact->preferredContact()->statusMessage().message();
402         }
403 
404         QStringList messages;
405         foreach (Kopete::Contact *subContact, contact->contacts()) {
406             QList<Kopete::MessageEvent *> pendingMessages = KopeteViewManager::viewManager()->pendingMessages(subContact);
407             foreach (Kopete::MessageEvent *event, pendingMessages) {
408                 messages << event->message().parsedBody();
409             }
410         }
411         properties[QStringLiteral("pending_messages")] = messages;
412     }
413 
414     return properties;
415 }
416