2
* %kadu copyright begin%
3
* Copyright 2009, 2010, 2011 Piotr Galiszewski (piotr.galiszewski@kadu.im)
4
* Copyright 2009 Bartłomiej Zimoń (uzi18@o2.pl)
5
* Copyright 2009, 2009, 2010, 2011 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com)
6
* Copyright 2010, 2011 Bartosz Brachaczek (b.brachaczek@gmail.com)
9
* This program is free software; you can redistribute it and/or
10
* modify it under the terms of the GNU General Public License as
11
* published by the Free Software Foundation; either version 2 of
12
* the License, or (at your option) any later version.
14
* This program is distributed in the hope that it will be useful,
15
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
* GNU General Public License for more details.
19
* You should have received a copy of the GNU General Public License
20
* along with this program. If not, see <http://www.gnu.org/licenses/>.
23
#include "accounts/account-manager.h"
24
#include "accounts/account.h"
25
#include "avatars/avatar-manager.h"
26
#include "avatars/avatar.h"
27
#include "buddies/buddy-manager.h"
28
#include "configuration/configuration-file.h"
29
#include "contacts/contact-details.h"
30
#include "contacts/contact-manager.h"
31
#include "core/core.h"
32
#include "misc/change-notifier.h"
33
#include "protocols/protocol.h"
34
#include "protocols/protocol-factory.h"
35
#include "protocols/protocols-manager.h"
36
#include "protocols/services/roster/roster-entry.h"
38
#include "contact-shared.h"
40
ContactShared * ContactShared::loadStubFromStorage(const QSharedPointer<StoragePoint> &storagePoint)
42
ContactShared *result = loadFromStorage(storagePoint);
48
ContactShared * ContactShared::loadFromStorage(const QSharedPointer<StoragePoint> &storagePoint)
50
ContactShared *result = new ContactShared();
51
result->setStorage(storagePoint);
56
ContactShared::ContactShared(const QUuid &uuid) :
57
Shared(uuid), Details(0),
58
Priority(-1), MaximumImageSize(0), UnreadMessagesCount(0),
59
Blocking(false), IgnoreNextStatusChange(false), Port(0)
61
Entry = new RosterEntry(this);
62
connect(Entry->changeNotifier(), SIGNAL(changed()), this, SIGNAL(dirtinessChanged()));
64
ContactAccount = new Account();
65
ContactAvatar = new Avatar();
66
OwnerBuddy = new Buddy();
68
connect(ProtocolsManager::instance(), SIGNAL(protocolFactoryRegistered(ProtocolFactory*)),
69
this, SLOT(protocolFactoryRegistered(ProtocolFactory*)));
70
connect(ProtocolsManager::instance(), SIGNAL(protocolFactoryUnregistered(ProtocolFactory*)),
71
this, SLOT(protocolFactoryUnregistered(ProtocolFactory*)));
73
connect(changeNotifier(), SIGNAL(changed()), this, SIGNAL(updated()));
76
ContactShared::~ContactShared()
80
disconnect(ProtocolsManager::instance(), 0, this, 0);
82
protocolFactoryUnregistered(ProtocolsManager::instance()->byName(ContactAccount->protocolName()));
86
delete ContactAccount;
89
StorableObject * ContactShared::storageParent()
91
return ContactManager::instance();
94
QString ContactShared::storageNodeName()
96
return QLatin1String("Contact");
99
void ContactShared::load()
101
if (!isValidStorage())
106
Id = loadValue<QString>("Id");
107
Priority = loadValue<int>("Priority", -1);
109
if (loadValue<bool>("Dirty", true))
110
Entry->setState(RosterEntryDesynchronized);
112
Entry->setState(RosterEntrySynchronized);
113
Entry->setDetached(loadValue<bool>("Detached", false));
115
*ContactAccount = AccountManager::instance()->byUuid(loadValue<QString>("Account"));
116
doSetOwnerBuddy(BuddyManager::instance()->byUuid(loadValue<QString>("Buddy")));
117
doSetContactAvatar(AvatarManager::instance()->byUuid(loadValue<QString>("Avatar")));
119
protocolFactoryRegistered(ProtocolsManager::instance()->byName(ContactAccount->protocolName()));
122
void ContactShared::aboutToBeRemoved()
124
// clean up references
125
*ContactAccount = Account::null;
127
doSetOwnerBuddy(Buddy::null);
129
AvatarManager::instance()->removeItem(*ContactAvatar);
130
doSetContactAvatar(Avatar::null);
134
changeNotifier()->notify();
137
void ContactShared::store()
139
if (!isValidStorage())
146
storeValue("Id", Id);
147
storeValue("Priority", Priority);
149
storeValue("Dirty", RosterEntrySynchronized != Entry->state());
150
storeValue("Detached", Entry->detached());
152
storeValue("Account", ContactAccount->uuid().toString());
153
storeValue("Buddy", !isAnonymous()
154
? OwnerBuddy->uuid().toString()
158
storeValue("Avatar", ContactAvatar->uuid().toString());
160
removeValue("Contact");
163
bool ContactShared::shouldStore()
167
if (!UuidStorableObject::shouldStore())
170
if (Id.isEmpty() || ContactAccount->uuid().isNull())
173
// we dont need data for non-roster contacts only from 4 version of sql schema
174
if (config_file.readNumEntry("History", "Schema", 0) < 4)
177
return !isAnonymous() || rosterEntry()->requiresSynchronization() || customProperties()->shouldStore();
180
void ContactShared::addToBuddy()
182
// dont add to buddy if details are not available
183
if (Details && *OwnerBuddy)
184
OwnerBuddy->addContact(this);
187
void ContactShared::removeFromBuddy()
190
OwnerBuddy->removeContact(this);
193
void ContactShared::setOwnerBuddy(const Buddy &buddy)
197
if (*OwnerBuddy == buddy)
200
/* NOTE: This guard is needed to avoid deleting this object when removing
201
* Contact from Buddy which may hold last reference to it and thus wants to
202
* delete it. But we don't want this to happen.
207
doSetOwnerBuddy(buddy);
210
Entry->setState(RosterEntryDesynchronized);
211
changeNotifier()->notify();
215
void ContactShared::setContactAccount(const Account &account)
219
if (*ContactAccount == account)
222
if (*ContactAccount && ContactAccount->protocolHandler() && ContactAccount->protocolHandler()->protocolFactory())
223
protocolFactoryUnregistered(ContactAccount->protocolHandler()->protocolFactory());
225
*ContactAccount = account;
227
if (*ContactAccount && ContactAccount->protocolHandler() && ContactAccount->protocolHandler()->protocolFactory())
228
protocolFactoryRegistered(ContactAccount->protocolHandler()->protocolFactory());
230
changeNotifier()->notify();
233
void ContactShared::protocolFactoryRegistered(ProtocolFactory *protocolFactory)
237
if (!protocolFactory || !*ContactAccount || ContactAccount->protocolName() != protocolFactory->name())
243
Details = protocolFactory->createContactDetails(this);
246
Details->ensureLoaded();
248
changeNotifier()->notify();
250
ContactManager::instance()->registerItem(this);
254
void ContactShared::protocolFactoryUnregistered(ProtocolFactory *protocolFactory)
258
if (!protocolFactory || ContactAccount->protocolName() != protocolFactory->name())
261
/* NOTE: This guard is needed to avoid deleting this object when detaching
262
* Contact from Buddy which may hold last reference to it and thus wants to
263
* delete it. But we don't want this to happen.
269
changeNotifier()->notify();
272
void ContactShared::deleteDetails()
276
// do not store contacts that are not in contact manager
277
if (ContactManager::instance()->allItems().contains(uuid()))
278
Details->ensureStored();
286
ContactManager::instance()->unregisterItem(this);
289
void ContactShared::setId(const QString &id)
299
Entry->setState(RosterEntryDesynchronized);
300
changeNotifier()->notify();
303
RosterEntry * ContactShared::rosterEntry()
311
* @todo: move this comment somewhere
313
* Sets state if this contact to \p dirty. All contacts are dirty by default.
315
* Dirty contacts with anonymous owner buddies are considered dirty removed and will
316
* never be added to roster as long as this state lasts and will in effect be removed
317
* from remote roster. Dirty contacts with not anonymous owner buddies are considered
318
* dirty added and will always be added to roster, even if remote roster marked
321
* When adding contacts with anononymous owner buddies to the manager, always make sure
322
* to mark them not dirty, otherwise they will be considered dirty removed and will
323
* not be added to roster if remote roster says so, which is probably not what one expects.
326
void ContactShared::avatarUpdated()
328
changeNotifier()->notify();
331
void ContactShared::doSetOwnerBuddy(const Buddy &buddy)
334
disconnect(*OwnerBuddy, 0, this, 0);
339
connect(*OwnerBuddy, SIGNAL(updated()), this, SIGNAL(buddyUpdated()));
342
void ContactShared::doSetContactAvatar(const Avatar &contactAvatar)
345
disconnect(*ContactAvatar, 0, this, 0);
347
*ContactAvatar = contactAvatar;
350
connect(*ContactAvatar, SIGNAL(updated()), this, SLOT(avatarUpdated()));
353
void ContactShared::setContactAvatar(const Avatar &contactAvatar)
357
if (*ContactAvatar == contactAvatar)
360
doSetContactAvatar(contactAvatar);
361
changeNotifier()->notify();
364
bool ContactShared::isAnonymous()
374
return OwnerBuddy->isAnonymous();
377
QString ContactShared::display(bool useBuddyData)
381
if (!useBuddyData || !OwnerBuddy || !(*OwnerBuddy) || OwnerBuddy->display().isEmpty())
384
return OwnerBuddy->display();
387
Avatar ContactShared::avatar(bool useBuddyData)
391
if (!useBuddyData || !OwnerBuddy || !(*OwnerBuddy) || OwnerBuddy->buddyAvatar().isEmpty())
392
return ContactAvatar ? *ContactAvatar : Avatar::null;
394
return OwnerBuddy->buddyAvatar();
397
KaduShared_PropertyPtrReadDef(ContactShared, Account, contactAccount, ContactAccount)
398
KaduShared_PropertyPtrReadDef(ContactShared, Avatar, contactAvatar, ContactAvatar)
399
KaduShared_PropertyPtrReadDef(ContactShared, Buddy, ownerBuddy, OwnerBuddy)