1 | /* |
2 | kopeteaccount.h - Kopete Account |
3 | |
4 | Copyright (c) 2007 by Gustavo Pichorim Boiko <gustavo.boiko@kdemail.net> |
5 | Copyright (c) 2003-2005 by Olivier Goffart <ogoffart@kde.org> |
6 | Copyright (c) 2003-2004 by Martijn Klingens <klingens@kde.org> |
7 | Copyright (c) 2004 by Richard Smith <kde@metafoo.co.uk> |
8 | |
9 | Kopete (c) 2002-2007 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 KOPETEACCOUNT_H |
22 | #define KOPETEACCOUNT_H |
23 | |
24 | #include "kopeteonlinestatus.h" |
25 | #include "kopetestatusmessage.h" |
26 | #include "kopete_export.h" |
27 | |
28 | #include <QtCore/QObject> |
29 | #include <QtGui/QPixmap> |
30 | #include <QtCore/QHash> |
31 | |
32 | #include <kconfiggroup.h> |
33 | #include <kiconloader.h> |
34 | #include <solid/networking.h> |
35 | |
36 | class ; |
37 | class KConfigGroup; |
38 | |
39 | namespace Kopete |
40 | { |
41 | class Contact; |
42 | class Protocol; |
43 | class MetaContact; |
44 | class Group; |
45 | class OnlineStatus; |
46 | class BlackLister; |
47 | class StatusMessage; |
48 | class Identity; |
49 | class PropertyContainer; |
50 | |
51 | /** |
52 | * The Kopete::Account class handles one account. |
53 | * Each protocol implementation should subclass this class in its own custom account class. |
54 | * There are a few pure virtual methods that must be implemented. Examples are: |
55 | * \li \ref connect() |
56 | * \li \ref disconnect() |
57 | * \li \ref createContact() |
58 | * |
59 | * The accountId is an @em constant unique id, which represents the login. |
60 | * The @ref myself() contact is one of the most important contacts, which represents |
61 | * the user tied to this account. You must create this contact in the contructor of your |
62 | * account and pass it to @ref setMyself(). |
63 | * |
64 | * All account data is saved to @ref KConfig. This includes the accountId, the autoconnect flag and |
65 | * the color. You can save more data using @ref configGroup() |
66 | * |
67 | * When you create a new account, you have to register it with the account manager by calling |
68 | * @ref AccountManager::registerAccount. |
69 | * |
70 | * @author Olivier Goffart <ogoffart\@kde.org> |
71 | */ |
72 | class KOPETE_EXPORT Account : public QObject |
73 | { |
74 | Q_OBJECT |
75 | |
76 | Q_ENUMS( AddMode ) |
77 | Q_PROPERTY( QString accountId READ accountId ) |
78 | Q_PROPERTY( bool excludeConnect READ excludeConnect WRITE setExcludeConnect ) |
79 | Q_PROPERTY( QColor color READ color WRITE setColor ) |
80 | Q_PROPERTY( QPixmap accountIcon READ accountIcon ) |
81 | Q_PROPERTY( bool isConnected READ isConnected ) |
82 | Q_PROPERTY( bool isAway READ isAway ) |
83 | Q_PROPERTY( bool suppressStatusNotification READ suppressStatusNotification ) |
84 | Q_PROPERTY( uint priority READ priority WRITE setPriority ) |
85 | |
86 | public: |
87 | /** |
88 | * \brief Describes how the account was disconnected |
89 | * |
90 | * Manual means that the disconnection was done by the user and no reconnection |
91 | * will take place. Any other value will reconnect the account on disconnection. |
92 | * The case where the password is wrong will be handled differently. |
93 | * @see @ref disconnected |
94 | */ |
95 | enum DisconnectReason { |
96 | OtherClient = -4, ///< connection went down because another client connected the same account |
97 | BadPassword = -3, ///< connection failed because password was incorrect |
98 | BadUserName = -2, ///< connection failed because user name was invalid / unknown |
99 | InvalidHost = -1, ///< connection failed because host is unreachable |
100 | Manual = 0, ///< the user disconnected normally |
101 | ConnectionReset = 1, ///< the connection was lost |
102 | Unknown = 99 ///< the reason for disconnection is unknown |
103 | }; |
104 | |
105 | /** |
106 | * \brief Describes what should be done when the contact is added to a metacontact |
107 | * @sa @ref addContact() |
108 | */ |
109 | enum AddMode { |
110 | ChangeKABC = 0, ///< The KDE Address book may be updated |
111 | DontChangeKABC = 1, ///< The KDE Address book will not be changed |
112 | Temporary = 2 ///< The contact will not be added on the contact list |
113 | }; |
114 | |
115 | /** |
116 | * \brief Describes what should be done when we set new OnlineStatus |
117 | * @sa @ref setOnlineStatus() |
118 | */ |
119 | enum OnlineStatusOption { |
120 | None = 0x00, ///< Use the online status |
121 | KeepSpecialFlags = 0x01 ///< Use the online status but keep special flags, e.g. Invisible |
122 | }; |
123 | Q_DECLARE_FLAGS(OnlineStatusOptions, OnlineStatusOption) |
124 | |
125 | /** |
126 | * Constructor for the Account object. |
127 | * |
128 | * @param parent the protocol for this account. The account is a child object of the |
129 | * protocol, so it will be automatically deleted when the protocol is. |
130 | * @param accountID the unique ID of this account. |
131 | * @param name the name of this QObject. |
132 | */ |
133 | Account(Protocol *parent, const QString &accountID); |
134 | |
135 | /** |
136 | * Destroy the Account object. |
137 | */ |
138 | ~Account(); |
139 | |
140 | /** |
141 | * \return the Protocol for this account |
142 | */ |
143 | Protocol *protocol() const ; |
144 | |
145 | /** |
146 | * \return the unique ID of this account used as the login |
147 | */ |
148 | QString accountId() const; |
149 | |
150 | /** |
151 | * The label for this account. |
152 | * |
153 | * This is used in the GUI. |
154 | * \return The label of this account |
155 | */ |
156 | QString accountLabel() const; |
157 | |
158 | /** |
159 | * \brief Get the priority of this account. |
160 | * |
161 | * Used for sorting and determining the preferred account to message a contact. |
162 | */ |
163 | uint priority() const; |
164 | |
165 | /** |
166 | * \brief Set the priority of this account. |
167 | * |
168 | * @note This method is called by the UI, and should not be called elsewhere. |
169 | */ |
170 | void setPriority( uint priority ); |
171 | |
172 | /** |
173 | * \brief Set if the account should not log in automatically. |
174 | * |
175 | * This function can be used by the EditAccountPage. Kopete handles connection automatically. |
176 | * @sa @ref excludeConnect |
177 | */ |
178 | void setExcludeConnect(bool); |
179 | |
180 | /** |
181 | * \brief Get if the account should not log in. |
182 | * |
183 | * @return @c true if the account should not be connected when connectAll at startup, @c false otherwise. |
184 | */ |
185 | bool excludeConnect() const; |
186 | |
187 | /** |
188 | * \brief Get the color for this account. |
189 | * |
190 | * The color will be used to visually differentiate this account from other accounts on the |
191 | * same protocol. |
192 | * |
193 | * \return the user color for this account |
194 | */ |
195 | const QColor color() const; |
196 | |
197 | /** |
198 | * \brief Set the color for this account. |
199 | * |
200 | * This is called by Kopete's account config page; you don't have to set the color yourself. |
201 | * |
202 | * @sa @ref color() |
203 | */ |
204 | void setColor( const QColor &color); |
205 | |
206 | /** |
207 | * \brief Get the icon for this account. |
208 | * |
209 | * Generates an image of size @p size representing this account. The result is not cached. |
210 | * |
211 | * @param size the size of the icon. If the size is 0, the default size is used. |
212 | * @return the icon for this account, colored if needed |
213 | */ |
214 | QPixmap accountIcon( const int size = 0 ) const; |
215 | |
216 | /* |
217 | * \brief Get the icon path for this account. |
218 | * |
219 | * This is the account icon path. |
220 | * |
221 | * @return the icon path for this account. |
222 | */ |
223 | QString accountIconPath(const KIconLoader::Group size) const; |
224 | |
225 | /** |
226 | * \brief change the account icon. |
227 | * by default the icon of an account is the protocol one, but it may be overide it. |
228 | * Set QString() to go back to the default (the protocol icon) |
229 | * |
230 | * this call will emit colorChanged() |
231 | */ |
232 | void setCustomIcon( const QString& ); |
233 | |
234 | /** |
235 | * \brief return the icon base |
236 | * This is the custom account icon set with setIcon. if this icon is null, then the protocol icon is used |
237 | * don't use this function to get the icon that need to be displayed, use accountIcon |
238 | */ |
239 | QString customIcon() const; |
240 | |
241 | /** |
242 | * \brief Retrieve the identity this account belongs to |
243 | * |
244 | * \return a pointer to the Identity object this account belongs to. |
245 | * |
246 | * \see setIdentity(). |
247 | */ |
248 | Identity * identity() const; |
249 | |
250 | /** |
251 | * \brief Sets the identity this account belongs to |
252 | * |
253 | * Setting the account to a new identity implies it to be removed from the |
254 | * identity it was previously associated. |
255 | * |
256 | * @param ident The identity this account should be associated to |
257 | * \return @c true if the identity was changed, @c false otherwise |
258 | * |
259 | * @note You should call the default implementation from your reimplementation |
260 | */ |
261 | virtual bool setIdentity( Kopete::Identity *ident ); |
262 | |
263 | /** |
264 | * \brief Retrieve the 'myself' contact. |
265 | * |
266 | * \return a pointer to the Contact object for this account |
267 | * |
268 | * \see setMyself(). |
269 | */ |
270 | Contact * myself() const; |
271 | |
272 | /** |
273 | * @brief Fill the menu with actions for this account |
274 | * |
275 | * You have to reimplement this method to add custom actions to the @p actionMenu which will |
276 | * be shown in the statusbar. It is the caller's responsibility to ensure the menu is deleted. |
277 | * |
278 | * The default implementation provides a generic menu, with actions generated from the protocol's |
279 | * registered statuses, and an action to show the account's settings dialog. |
280 | * |
281 | * You should call the default implementation from your reimplementation, and add more actions |
282 | * you require to the resulting action menu. |
283 | * |
284 | * @see OnlineStatusManager::registerOnlineStatus |
285 | */ |
286 | virtual void ( KActionMenu * ); |
287 | |
288 | /** |
289 | * @brief Return true if account has custom status menu. |
290 | * |
291 | * You have to reimplement this method and return true if you don't want to have status menu in menu |
292 | * which will be shown in the statusbar |
293 | * |
294 | * The default implementation returns false. |
295 | */ |
296 | virtual bool () const; |
297 | |
298 | /** |
299 | * @brief Retrieve the list of contacts for this account (except myself contact) |
300 | * |
301 | * The list is guaranteed to contain only contacts for this account, |
302 | * so you can safely use static_cast to your own derived contact class |
303 | * if needed. |
304 | */ |
305 | const QHash<QString,Contact*>& contacts(); |
306 | |
307 | /** |
308 | * Indicates whether or not we should suppress status notifications |
309 | * for contacts belonging to this account. |
310 | * |
311 | * This is used when we just connected or disconnected, and every contact has their initial |
312 | * status set. |
313 | * |
314 | * @return @c true if notifications should not be used, @c false otherwise |
315 | */ |
316 | bool suppressStatusNotification() const; |
317 | |
318 | /** |
319 | * \brief Create a contact (creating a new metacontact if necessary) |
320 | * |
321 | * If a contact for this account with ID @p contactId is not already on the contact list, |
322 | * a new contact with that ID is created, and added to a new metacontact. |
323 | * |
324 | * If @p mode is @c ChangeKABC, MetaContact::updateKABC will be called on the resulting metacontact. |
325 | * If @p mode is @c Temporary, MetaContact::setTemporary will be called on the resulting metacontact, |
326 | * and the metacontact will not be added to @p group. |
327 | * If @p mode is @c DontChangeKABC, no additional action is carried out. |
328 | * |
329 | * @param contactId the @ref Contact::contactId of the contact to create |
330 | * @param displayName the displayname (alias) of the new metacontact. Leave as QString() if |
331 | * no alias is known, then by default, the nick will be taken as alias and tracked if changed. |
332 | * @param group the group to add the created metacontact to, or 0 for the top-level group. |
333 | * @param mode the mode used to add the contact. Use DontChangeKABC when deserializing. |
334 | * @return the new created metacontact or 0L if the operation failed |
335 | */ |
336 | MetaContact* addContact( const QString &contactId, const QString &displayName = QString(), Group *group = 0, AddMode mode = DontChangeKABC ); |
337 | |
338 | /** |
339 | * @brief Create a new contact, adding it to an existing metacontact |
340 | * |
341 | * If a contact for this account with ID @p contactId is not already on the contact list, |
342 | * a new contact with that ID is created, and added to the metacontact @p parent. |
343 | * |
344 | * @param contactId the @ref Contact::contactId of the contact to create |
345 | * @param parent the parent metacontact (must not be 0) |
346 | * @param mode the mode used to add the contact. See addContact(const QString&,const QString&,Group*,AddMode) for details. |
347 | * |
348 | * @return @c true if creation of the contact succeeded or the contact was already in the list, |
349 | * @c false otherwise. |
350 | */ |
351 | bool addContact( const QString &contactId, MetaContact *parent, AddMode mode = DontChangeKABC ); |
352 | |
353 | /** |
354 | * @brief Indicate whether the account is connected at all. |
355 | * |
356 | * This is a convenience method that calls @ref Contact::isOnline() on @ref myself(). |
357 | * This function is safe to call if @ref setMyself() has not been called yet. |
358 | * |
359 | * @see @ref isConnectedChanged() |
360 | */ |
361 | bool isConnected() const; |
362 | |
363 | /** |
364 | * @brief Indicate whether the account is away. |
365 | * |
366 | * This is a convenience method that queries @ref Contact::onlineStatus() on @ref myself(). |
367 | * This function is safe to call if @ref setMyself() has not been called yet. |
368 | * |
369 | * @see @ref isBusy() |
370 | */ |
371 | bool isAway() const; |
372 | |
373 | /** |
374 | * @brief Indicate whether the account is busy. |
375 | * |
376 | * In busy mode all visible and sound events should be disabled. |
377 | * |
378 | * This is a convenience method that queries @ref Contact::onlineStatus() on @ref myself(). |
379 | * This function is safe to call if @ref setMyself() has not been called yet. |
380 | * |
381 | * @see @ref isAway() |
382 | */ |
383 | bool isBusy() const; |
384 | |
385 | /** |
386 | * Return the @ref KConfigGroup used to write and read special properties |
387 | * |
388 | * "Protocol", "AccountId" , "Color", "AutoConnect", "Priority", "Enabled" , "Icon" are reserved keyword |
389 | * already in use in that group. |
390 | * |
391 | * for compatibility, try to not use key that start with a uppercase |
392 | */ |
393 | KConfigGroup *configGroup() const; |
394 | |
395 | /** |
396 | * @brief Remove the account from the server. |
397 | * |
398 | * Reimplement this if your protocol supports removing the accounts from the server. |
399 | * This function is called by @ref AccountManager::removeAccount typically when you remove the |
400 | * account on the account config page. |
401 | * |
402 | * You should add a confirmation message box before removing the account. The default |
403 | * implementation does nothing. |
404 | * |
405 | * @return @c false only if the user requested for the account to be deleted, and deleting the |
406 | * account failed. Returns @c true in all other cases. |
407 | */ |
408 | virtual bool removeAccount(); |
409 | |
410 | /** |
411 | * \return a pointer to the blacklist of the account |
412 | * @todo remove or implement correctly (BlackLister) |
413 | */ |
414 | BlackLister* blackLister(); |
415 | |
416 | /** |
417 | * \return @c true if the contact with ID @p contactId is in the blacklist, @c false otherwise. |
418 | * @todo remove or implement correctly (BlackLister) |
419 | */ |
420 | virtual bool isBlocked( const QString &contactId ); |
421 | |
422 | protected: |
423 | /** |
424 | * \brief Set the 'myself' contact. |
425 | * |
426 | * This contact must be defined for every account, because it holds the online status |
427 | * of the account. You must call this function in the constructor of your account. |
428 | * |
429 | * The myself contact can't be deleted as long as the account still exists. The myself |
430 | * contact is used as a member of every ChatSession involving this account. myself's |
431 | * contactId should be the accountID. The online status of the myself contact represents |
432 | * the account's status. |
433 | * |
434 | * The myself should have the @ref ContactList::myself() as parent metacontact |
435 | * |
436 | */ |
437 | void setMyself( Contact *myself ); |
438 | |
439 | /** |
440 | * \brief Create a new contact in the specified metacontact |
441 | * |
442 | * You shouldn't ever call this method yourself. To add contacts, use @ref addContact(). |
443 | * |
444 | * This method is called by @ref addContact(). In this method, you should create the |
445 | * new custom @ref Contact, using @p parentContact as the parent. |
446 | * |
447 | * If the metacontact is not temporary and the protocol supports it, you can add the |
448 | * contact to the server. |
449 | * |
450 | * @param contactId the ID of the contact to create |
451 | * @param parentContact the metacontact to add this contact to |
452 | * @return @c true if creating the contact succeeded, @c false on failure. |
453 | */ |
454 | virtual bool createContact( const QString &contactId, MetaContact *parentContact ) =0; |
455 | |
456 | |
457 | /** |
458 | * \brief Sets the account label |
459 | * |
460 | * @param label The label to set |
461 | */ |
462 | void setAccountLabel( const QString &label ); |
463 | |
464 | protected slots: |
465 | /** |
466 | * \brief The service has been disconnected |
467 | * |
468 | * You have to call this method when you are disconnected. Depending on the value of |
469 | * @p reason, this function may attempt to reconnect to the server. |
470 | * |
471 | * - BadPassword will ask again for the password |
472 | * - OtherClient will show a message box |
473 | * |
474 | * @param reason the reason for the disconnection. |
475 | */ |
476 | virtual void disconnected( Kopete::Account::DisconnectReason reason ); |
477 | |
478 | /** |
479 | * @brief Sets the online status of all contacts in this account to the same value |
480 | * |
481 | * Some protocols do not provide status-changed events for all contacts when an account |
482 | * becomes connected or disconnected. For such protocols, this function may be useful |
483 | * to set all contacts offline. |
484 | * |
485 | * Calls @ref Kopete::Contact::setOnlineStatus on all contacts of this account (except the |
486 | * @ref myself() contact), passing @p status as the status. |
487 | * |
488 | * @param status the status to set all contacts of this account except @ref myself() to. |
489 | */ |
490 | void setAllContactsStatus( const Kopete::OnlineStatus &status ); |
491 | |
492 | /** |
493 | * @brief React to network status changes |
494 | * |
495 | * @param status the new network status. |
496 | */ |
497 | void networkingStatusChanged( const Solid::Networking::Status status ); |
498 | |
499 | signals: |
500 | /** |
501 | * The color of the account has been changed |
502 | * |
503 | * also emitted when the icon change |
504 | * @todo probably rename to accountIconChanged |
505 | */ |
506 | void colorChanged( const QColor & ); |
507 | |
508 | /** |
509 | * Emitted when the account is deleted. |
510 | * @warning emitted in the Account destructor. It is not safe to call any functions on @p account. |
511 | */ |
512 | void accountDestroyed( const Kopete::Account *account ); |
513 | |
514 | /** |
515 | * Emitted whenever @ref isConnected() changes. |
516 | */ |
517 | void isConnectedChanged(); |
518 | |
519 | private: |
520 | /** |
521 | * @internal |
522 | * Reads the configuration information of the account from KConfig. |
523 | */ |
524 | void readConfig(); |
525 | |
526 | public: |
527 | /** |
528 | * @internal |
529 | * Register a new Contact with the account. This should be called @em only from the |
530 | * @ref Contact constructor, not from anywhere else (not even a derived class). |
531 | */ |
532 | bool registerContact( Contact *c ); |
533 | |
534 | public slots: |
535 | /** |
536 | * @brief Go online for this service. |
537 | * |
538 | * @param initialStatus is the status to connect with. If it is an invalid status for this |
539 | * account, the default online for the account should be used. |
540 | * @todo probably deprecate in favor of setOnlineStatus |
541 | */ |
542 | virtual void connect( const Kopete::OnlineStatus& initialStatus = OnlineStatus() ) = 0; |
543 | |
544 | /** |
545 | * @brief Go offline for this service. |
546 | * |
547 | * If the service is connecting, you should abort the connection. |
548 | * |
549 | * You should call the @ref disconnected function from this function. |
550 | * @todo probably deprecate in favor of setOnlineStatus |
551 | */ |
552 | virtual void disconnect( ) = 0 ; |
553 | |
554 | public slots: |
555 | /** |
556 | * Reimplement this function to set the online status |
557 | * @param status is the new status |
558 | * @param reason is the status message to set. |
559 | * @param options specify how the status should be set |
560 | * @note If needed, you need to connect. if the offline status is given, you should disconnect |
561 | */ |
562 | virtual void setOnlineStatus( const Kopete::OnlineStatus& status, |
563 | const Kopete::StatusMessage &reason = Kopete::StatusMessage(), |
564 | const OnlineStatusOptions& options = None ) = 0; |
565 | /** |
566 | * Reimplement this function to set the status message(with metadata). |
567 | * You should use this method to set the status message instead of using setOnlineStatus. |
568 | * @param statusMessage is the status message to set. (Use Kopete::StatusMessage). |
569 | */ |
570 | virtual void setStatusMessage( const Kopete::StatusMessage &statusMessage ) = 0; |
571 | |
572 | /** |
573 | * Disconnects account, required before resume() |
574 | * Returns false if account is already suspended. |
575 | */ |
576 | bool suspend( const Kopete::StatusMessage &reason = Kopete::StatusMessage() ); |
577 | |
578 | /** |
579 | * Sets account to the online status that was active when suspend() was called. |
580 | * Returns false if account has not been suspended or status has changed to something other than Offline in the meantime. |
581 | */ |
582 | bool resume(); |
583 | |
584 | /** |
585 | * Display the edit account widget for the account |
586 | */ |
587 | void editAccount( QWidget* parent = 0L ); |
588 | |
589 | /** |
590 | * Add a user to the blacklist. The default implementation calls |
591 | * blackList()->addContact( contactId ) |
592 | * |
593 | * @param contactId the contact to be added to the blacklist |
594 | * @todo remove or implement correctly (BlackLister) |
595 | */ |
596 | virtual void block( const QString &contactId ); |
597 | |
598 | /** |
599 | * Remove a user from the blacklist. The default implementation calls |
600 | * blackList()->removeContact( contactId ) |
601 | * |
602 | * @param contactId the contact to be removed from the blacklist |
603 | * @todo remove or implement correctly (BlackLister) |
604 | */ |
605 | virtual void unblock( const QString &contactId ); |
606 | |
607 | private slots: |
608 | /** |
609 | * Restore online status and status message on reconnect. |
610 | */ |
611 | void reconnect(); |
612 | |
613 | /** |
614 | * Track the deletion of a Contact and clean up |
615 | */ |
616 | void contactDestroyed( Kopete::Contact * ); |
617 | |
618 | /** |
619 | * The @ref myself() contact's online status changed. |
620 | */ |
621 | void slotOnlineStatusChanged( Kopete::Contact *contact, const Kopete::OnlineStatus &newStatus, const Kopete::OnlineStatus &oldStatus ); |
622 | |
623 | /** |
624 | * The @ref myself() contact's property changed. |
625 | */ |
626 | void slotContactPropertyChanged( Kopete::PropertyContainer *, const QString &, const QVariant &, const QVariant & ); |
627 | |
628 | /** |
629 | * Stop the suppression of status notification (connected to a timer) |
630 | */ |
631 | void slotStopSuppression(); |
632 | |
633 | private: |
634 | class Private; |
635 | Private * const d; |
636 | }; |
637 | Q_DECLARE_OPERATORS_FOR_FLAGS(Account::OnlineStatusOptions) |
638 | |
639 | } //END namespace Kopete |
640 | |
641 | #endif |
642 | |
643 | |