1/*
2 kopetemetacontact.h - Kopete Meta Contact
3
4 Copyright (c) 2002-2003 by Martijn Klingens <klingens@kde.org>
5 Copyright (c) 2002-2005 by Duncan Mac-Vicar Prett <duncan@kde.org>
6 Copyright (c) 2002-2005 by Olivier Goffart <ogoffart@kde.org>
7 Copyright (c) 2003 by Will Stephenson <will@stevello.free-online.co.uk>
8
9 Kopete (c) 2002-2005 by the Kopete developers <kopete-devel@kde.org>
10
11 *************************************************************************
12 * *
13 * This library is free software; you can redistribute it and/or *
14 * modify it under the terms of the GNU Lesser General Public *
15 * License as published by the Free Software Foundation; either *
16 * version 2 of the License, or (at your option) any later version. *
17 * *
18 *************************************************************************
19*/
20
21#ifndef kopetemetacontact_h__
22#define kopetemetacontact_h__
23
24#include "kopetecontactlistelement.h"
25
26#include <QtCore/QList>
27#include <QtCore/QUuid>
28
29#include <kdemacros.h>
30#include <kurl.h>
31#include "kopete_export.h"
32
33#include "kopeteonlinestatus.h"
34#include "kopetestatusmessage.h"
35
36namespace Kopete {
37
38
39class Plugin;
40class Group;
41class Picture;
42
43/**
44 * @author Will Stephenson <will@stevello.free-online.co.uk>
45 * @author Martijn Klingens <klingens@kde.org>
46 * @author Duncan Mac-Vicar Prett <duncan@kde.org>
47 * @author Olivier Goffart <ogoffart@kde.org>
48 *
49 * A metacontact represent a person. This is a kind of entry to
50 * the contact list. All information of a contact is contained in
51 * the metacontact. Plugins can store data in it with all
52 * @ref ContactListElement methods
53 */
54class KOPETE_EXPORT MetaContact : public ContactListElement
55{
56 Q_OBJECT
57
58 Q_PROPERTY( QString displayName READ displayName WRITE setDisplayName )
59 Q_PROPERTY( QString statusString READ statusString )
60 Q_PROPERTY( QString statusIcon READ statusIcon )
61 Q_PROPERTY( bool isOnline READ isOnline )
62 Q_PROPERTY( bool isReachable READ isReachable )
63 Q_PROPERTY( bool isTemporary READ isTemporary )
64 Q_PROPERTY( bool canAcceptFiles READ canAcceptFiles )
65 //Q_PROPERTY( ulong idleTime READ idleTime )
66 Q_PROPERTY( QUuid metaContactId READ metaContactId WRITE setMetaContactId )
67 Q_PROPERTY( bool photoSyncedWithKABC READ isPhotoSyncedWithKABC WRITE setPhotoSyncedWithKABC )
68
69public:
70 typedef QList<MetaContact *> List;
71 /**
72 * Enumeration of possible sources for a property (which may be
73 * photos, see setPhotoSource() for instance).
74 */
75 enum PropertySource {
76 SourceContact /**< Data comes from the contact itself. */,
77 SourceKABC /**< Data comes from KABC (addressbook). */,
78 SourceCustom /**< Data comes from somewhere else. */
79 };
80
81 /**
82 * constructor
83 */
84 MetaContact();
85 /**
86 * destructor
87 */
88 ~MetaContact();
89
90 /**
91 * @brief Returns this metacontact's ID.
92 *
93 * Every metacontact has a unique id, set when creating the contact,
94 * or reading the contactlist
95 */
96 QUuid metaContactId() const;
97
98 /**
99 * @internal
100 * Set the meta contact id for this meta contact to use. It should only
101 * be used by the contact list loading mechanism
102 */
103 void setMetaContactId( const QUuid& newMetaContactId );
104
105 /**
106 * @brief Get the KABC id for this metacontact
107 */
108 QString kabcId() const;
109
110 /**
111 * @brief Set the KABC id for this metacontact
112 * Use with care! You could create a one to many relationship
113 */
114 void setKabcId( const QString& newKabcId );
115
116 /**
117 * @brief Retrieve the list of contacts that are part of the meta contact
118 */
119 QList<Contact *> contacts() const;
120
121 /**
122 * @brief The groups the contact is stored in
123 */
124 QList<Group *> groups() const;
125
126 /**
127 * Find the Contact to a given contact. If contact
128 * is not found, a null pointer is returned.
129 * if @p protocolId or @p accountId are null, it is searched over all protocols/accounts
130 */
131 Contact *findContact( const QString &protocolId, const QString &accountId, const QString &contactId );
132
133 /**
134 * @brief Set the source of metacontact displayName
135 *
136 * This method selects the display name source for one
137 * of the sources defined in @ref PropertySource
138 *
139 * @see PropertySource
140 */
141 void setDisplayNameSource(PropertySource source);
142
143 void setDisplayNameSource( const QString &nameSourcePID, const QString &nameSourceAID, const QString &nameSourceCID );
144
145 /**
146 * @brief get the source of metacontact display name
147 *
148 * This method obtains the current name source for one
149 * of the sources defined in @ref PropertySource
150 *
151 * @see PropertySource
152 */
153 PropertySource displayNameSource() const;
154
155 /**
156 * @brief Set the source of metacontact photo
157 *
158 * This method selects the photo source for one
159 * of the sources defined in @ref PropertySource
160 *
161 * @see PropertySource
162 */
163 void setPhotoSource(PropertySource source);
164
165 void setPhotoSource( const QString &photoSourcePID, const QString &photoSourceAID, const QString &photoSourceCID );
166
167 /**
168 * @brief get the source of metacontact photo
169 *
170 * This method obtains the current photo source for one
171 * of the sources defined in @ref PropertySource
172 *
173 * @see PropertySource
174 */
175 PropertySource photoSource() const;
176
177 /**
178 * @brief the display name showed in the contact list window
179 *
180 * The displayname is the name which should be shown almost everywere to
181 * represent the metacontact. (in the contact list, in the chatwindow, ...)
182 *
183 * This is a kind of alias, set by the kopete user, as opposed to a nickname
184 * set by the contact itself.
185 *
186 * If the protocol support alias serverside, the metacontact displayname
187 * should probably be synchronized with the alias on the server.
188 *
189 * This displayName is obtained from the source set with @ref setDisplayNameSource
190 */
191 QString displayName() const;
192
193 /**
194 * @brief the photo showed in the contact list window
195 *
196 * Returns a image for the metacontact. If the metacontact photo source is
197 * the KDE addressbook. it will return the picture stored in the addressbook
198 * It can also use a subcontact as the photo source.
199 *
200 * This photo is obtained from the source set with @ref setPhotoSource
201 * @deprecated Use picture().image() instead.
202 */
203 KDE_DEPRECATED QImage photo() const;
204
205 /**
206 * Return the correct Kopete::Picture object depending of the metacontact photo source.
207 *
208 * This photo is obtained from the source set with @ref setPhotoSource
209 *
210 * KDE4 TODO: Rename this to photo() and use the new object.
211 */
212 Picture &picture() const;
213
214 /**
215 * @brief Set the custom displayName.
216 *
217 * This display name is used when name source is Custom
218 * this metohd may emit @ref displayNameChanged signal.
219 * And will call @ref Kopete::Contact::sync
220 *
221 * @see displayName()
222 * @see displayNameSource()
223 */
224 void setDisplayName( const QString &name );
225
226 /**
227 * @brief Returns the custom display name
228 *
229 * @see displayName()
230 * @see displayNameSource()
231 */
232 QString customDisplayName() const;
233
234 /**
235 * @brief Returns the custom display photo
236 *
237 * @see photo()
238 * @see photoSource()
239 */
240 KUrl customPhoto() const;
241
242
243 /**
244 * @brief Set the custom photo.
245 *
246 * This photo is used when photo source is set toCustom
247 * this metohd may emit @ref photoChanged signal.
248 *
249 * @see photo()
250 * @see photoSource()
251 */
252 void setPhoto( const KUrl &url );
253
254 /**
255 * @brief get the subcontact being tracked for its displayname (null if not set)
256 *
257 * The MetaContact will adjust its displayName() every time the
258 * "nameSource" changes its nickname property.
259 */
260 Contact *displayNameSourceContact() const;
261
262 /**
263 * @brief set the subcontact whose name is to be tracked (set to null to disable tracking)
264 * @see nameSource
265 */
266 void setDisplayNameSourceContact( Contact* contact );
267
268 /**
269 * @brief get the subcontact being tracked for its photo
270 */
271 Contact *photoSourceContact() const;
272
273 /**
274 * @brief set the subcontact to use for SourceContact source
275 */
276 void setPhotoSourceContact( Contact* contact );
277
278 /**
279 * @return true if when a subcontact change his photo, the photo will be set to the kabc contact.
280 */
281 bool isPhotoSyncedWithKABC() const;
282
283 /**
284 * Set if the photo should be synced with the adressbook when the photosource change his photo
285 *
286 * If \p b is true, the photo will be synced immediately if possible
287 */
288 void setPhotoSyncedWithKABC(bool b);
289
290
291 /**
292 * Temporary contacts will not be serialized.
293 * If they are added to the contact list, they appears in a special "Not in your contact list" group.
294 * (the @ref Group::temporary group)
295 */
296 bool isTemporary() const;
297
298 /**
299 * @brief Add a contact which has just been deserialised to the meta contact
300 * @param c The Contact being added
301 */
302 void addContact( Contact *c );
303
304 /**
305 * @brief remove the contact from this metacontact
306 *
307 * set 'deleted' to true if the Contact is already deleted
308 *
309 * @param c is the contact to remove
310 * @param deleted : if it is false, it will disconnect the old contact, and call some method.
311 */
312 void removeContact( Contact *c , bool deleted = false );
313
314 /**
315 * @return the preferred child Contact for communication, or 0 if none is suitable (all unreachable).
316 */
317 Contact *preferredContact();
318
319 /**
320 * @brief The name of the icon associated with the contact's status
321 * @todo improve with OnlineStatus
322 */
323 QString statusIcon() const;
324
325 /**
326 * @brief The status string of the contact
327 *
328 * @see @ref status()
329 * @todo improve with OnlineStatus
330 */
331 QString statusString() const;
332
333 /**
334 * Returns whether this contact can be reached online for at least one
335 * FIXME: Make that an enum, because status can be unknown for certain
336 * protocols
337 */
338 bool isOnline() const;
339
340 /**
341 * Returns whether this contact is visible even if offline
342 */
343 bool isAlwaysVisible() const;
344
345 /**
346 * Returns whether this contact can accept files
347 * @return True if the user is online with a file capable protocol, false otherwise
348 */
349 bool canAcceptFiles() const;
350
351 /**
352 * Return a more fine-grained status.
353 * Online means at least one sub-contact is online, away means at least
354 * one is away, but nobody is online and offline speaks for itself
355 */
356 OnlineStatus::StatusType status() const;
357
358 /**
359 * Like isOnline, but returns true even if the contact is not online, but
360 * can be reached trough offline-messages.
361 * it it return false, you are unable to open a chatwindow
362 * @todo : Here too, use preference order, not append order!
363 * @todo : Here too an enum.
364 */
365 bool isReachable() const;
366
367 /**
368 * return the time in second the contact is idle.
369 */
370 quint32 idleTime() const;
371
372 /**
373 * Get or set a field for the KDE address book backend. Fields not
374 * registered during the call to Plugin::addressBookFields()
375 * cannot be altered!
376 *
377 * @param p The Plugin by which uses this field
378 * @param app refers to the application id in the libkabc database.
379 * This should be a standardized format to make sense in the address
380 * book in the first place - if you could use "" as application
381 * then probably you should use the plugin data API instead of the
382 * address book fields.
383 * @param key The name of the address book field to get or set
384 *
385 * @todo: In the code the requirement that fields are registered first
386 * is already lifted, but the API needs some review before we
387 * can remove it here too.
388 * Probably it requires once more some rewrites to get it working
389 * properly :( - Martijn
390 */
391 QString addressBookField( Plugin *p, const QString &app, const QString &key ) const;
392
393 /**
394 * @brief set an address book field
395 *
396 * @see also @ref addressBookField()
397 * @param p The Plugin by which uses this field
398 * @param app The application ID in the KABC database
399 * @param key The name of the address book field to set
400 * @param value The value of the address book field to set
401 */
402 void setAddressBookField( Plugin *p, const QString &app, const QString &key, const QString &value );
403
404 /**
405 * @brief The status message of metacontact
406 */
407 StatusMessage statusMessage() const;
408
409public slots:
410
411 /**
412 * @brief Send a file to this metacontact
413 *
414 * This is the MetaContact level slot for sending files. It may be called through the
415 * "Send File" entry in the GUI, or over DCOP. If the function is called through the GUI,
416 * no parameters are sent and they assume default values. This slot calls the slotSendFile
417 * with identical params of the highest ranked contact capable of sending files (if any)
418 *
419 * @param sourceURL The actual KUrl of the file you are sending
420 * @param altFileName (Optional) An alternate name for the file - what the receiver will see
421 * @param fileSize (Optional) Size of the file being sent. Used when sending a nondeterminate
422 * file size (such as over a socket)
423 *
424 */
425 void sendFile( const KUrl &sourceURL, const QString &altFileName = QString(),
426 unsigned long fileSize = 0L );
427
428 /**
429 * Serialize this metaContact
430 * This causes each Kopete::Protocol subclass to serialise its contacts' data into the metacontact's plugin data
431 */
432 void serialize();
433
434signals:
435 /**
436 * One of the subcontacts' idle status has changed. As with online status,
437 * this can occur without the metacontact changing idle state
438 */
439 void contactIdleStateChanged( Kopete::Contact *contact );
440
441 /**
442 * Status title or message has changed
443 */
444 void statusMessageChanged( Kopete::MetaContact *metaContact );
445
446public slots:
447
448 /**
449 * @brief Move a contact from one group to another.
450 */
451 void moveToGroup( Kopete::Group *from, Kopete::Group *to );
452
453 /**
454 * @brief Remove a contact from one group
455 */
456 void removeFromGroup( Kopete::Group *from );
457
458 /**
459 * @brief Add a contact to another group.
460 */
461 void addToGroup( Kopete::Group *to );
462
463 /**
464 * @brief Set if this is a temporary contact. (see @ref isTemporary)
465 *
466 * @param b if the contact is or not temporary
467 * @param group if the contact was temporary and b is false, then the contact will be moved to this group.
468 * if group is null, it will be moved to top-level
469 */
470 void setTemporary( bool b = true, Kopete::Group *group = 0L );
471
472 /**
473 * @brief Contact another user.
474 *
475 * Depending on the config settings, call sendMessage() or
476 * startChat()
477 *
478 * returns the Contact that was chosen as the preferred
479 */
480 Contact *execute();
481
482 /**
483 * @brief Send a single message, classic ICQ style.
484 *
485 * The actual sending is done by the Contact, but the meta contact
486 * does the GUI side of things.
487 * This is a slot to allow being called easily from e.g. a GUI.
488 *
489 * returns the Contact that was chosen as the preferred
490 */
491 Contact *sendMessage();
492
493 /**
494 * @brief Start a chat in a persistent chat window
495 *
496 * Like sendMessage, but this time a full-blown chat will be opened.
497 * Most protocols can't distinguish between the two and are either
498 * completely session based like MSN or completely message based like
499 * ICQ the only true difference is the GUI shown to the user.
500 *
501 * returns the Contact that was chosen as the preferred
502 */
503 Contact *startChat();
504
505 /**
506 * When all the plugins are loaded, set the Contact Source.
507 */
508 void slotAllPluginsLoaded();
509
510 /**
511 * If a plugin is loaded, maybe data about this plugin are already cached in the metacontact
512 */
513 void slotPluginLoaded( Kopete::Plugin *plugin );
514
515 /**
516 * If a protocol is loaded, deserialize cached data
517 */
518 void slotProtocolLoaded( Kopete::Protocol *p );
519
520signals:
521 /**
522 * @brief The MetaContact online status changed
523 */
524 void onlineStatusChanged( Kopete::MetaContact *contact, Kopete::OnlineStatus::StatusType status );
525
526 /**
527 * @brief A contact's online status changed
528 *
529 * this signal differs from @ref onlineStatusChanged because a contact can
530 * change his status without changing MetaContact status. It is mainly used to update the small icons
531 * in the contact list
532 */
533 void contactStatusChanged( Kopete::Contact *contact, const Kopete::OnlineStatus &status );
534
535 /**
536 * @brief The meta contact's display name changed
537 */
538 void displayNameChanged( const QString &oldName, const QString &newName );
539
540 /**
541 * @brief The meta contact's photo changed
542 */
543 void photoChanged();
544
545 /**
546 * @brief The contact was moved
547 */
548 void movedToGroup( Kopete::MetaContact *contact, Kopete::Group *from, Kopete::Group *to );
549
550 /**
551 * @brief The contact was removed from group
552 */
553 void removedFromGroup( Kopete::MetaContact *contact, Kopete::Group *group );
554
555 /**
556 * @brief The contact was added to another group
557 */
558 void addedToGroup( Kopete::MetaContact *contact, Kopete::Group *to );
559
560 /**
561 * @brief a contact has been added into this metacontact
562 *
563 * This signal is emitted when a contact is added to this metacontact
564 */
565 void contactAdded( Kopete::Contact *c );
566
567 /**
568 * @brief a contact has been removed from this metacontact
569 *
570 * This signal is emitted when a contact is removed from this metacontact
571 */
572 void contactRemoved( Kopete::Contact *c );
573
574 /**
575 * Some part of this object's persistent data (as returned by toXML) has changed.
576 */
577 void persistentDataChanged( );
578
579private slots:
580 /**
581 * Update the contact's online status and emit onlineStatusChanged
582 * when appropriate
583 */
584 void updateOnlineStatus();
585
586 /**
587 * One of the child contact's online status changed
588 */
589 void slotContactStatusChanged( Kopete::Contact *c, const Kopete::OnlineStatus &status, const Kopete::OnlineStatus &oldStatus );
590
591 /**
592 * One of the child contact's property changed
593 */
594 void slotPropertyChanged( Kopete::PropertyContainer *contact, const QString &key, const QVariant &oldValue, const QVariant &newValue );
595
596 void slotContactDisplayNameChanged( const QString &oldName, const QString &newName );
597
598 /**
599 * A child contact was deleted, remove it from the list, if it's still
600 * there
601 */
602 void slotContactDestroyed( Kopete::Contact* );
603
604 /**
605 * Update the KABC Picture when the addressbook is changed.
606 */
607 void slotUpdateAddressBookPicture();
608
609protected:
610 //QImage photoFromContact( Kopete::Contact *c) const;
611 //QImage photoFromKABC( const QString &id ) const;
612 QImage photoFromCustom() const;
613 //QString nameFromContact( Kopete::Contact *c) const;
614 //QString nameFromKABC( const QString &id ) const;
615
616 void onlineStatusNotification( Kopete::Contact * c );
617
618private:
619 class Private;
620 Private * const d;
621};
622
623// util functions shared with metacontact property dialog
624KOPETE_EXPORT QImage photoFromContact( Kopete::Contact *c) /*const*/;
625KOPETE_EXPORT QImage photoFromKABC( const QString &id ) /*const*/;
626KOPETE_EXPORT QString nameFromContact( Kopete::Contact *c) /*const*/;
627KOPETE_EXPORT QString nameFromKABC( const QString &id ) /*const*/;
628
629} //END namespace Kopete
630
631
632#endif
633
634// vim: set noet ts=4 sts=4 sw=4:
635
636