less Q3 (remove a lot of unused Q3 headers, port small things)
[kdenetwork.git] / kopete / libkopete / kopetecontact.cpp
blob419b7c8757f5a287aaa02290afd6bd58282f1125
1 /*
2 kopetecontact.cpp - Kopete Contact
4 Copyright (c) 2002-2004 by Duncan Mac-Vicar Prett <duncan@kde.org>
5 Copyright (c) 2002-2003 by Martijn Klingens <klingens@kde.org>
6 Copyright (c) 2002-2004 by Olivier Goffart <ogoffart @tiscalinet.be>
8 Kopete (c) 2002-2004 by the Kopete developers <kopete-devel@kde.org>
10 *************************************************************************
11 * *
12 * This library is free software; you can redistribute it and/or *
13 * modify it under the terms of the GNU Lesser General Public *
14 * License as published by the Free Software Foundation; either *
15 * version 2 of the License, or (at your option) any later version. *
16 * *
17 *************************************************************************
20 #include "kopetecontact.h"
22 #include <qapplication.h>
23 #include <Q3StyleSheet>
25 #include <kdebug.h>
27 #include <kdeversion.h>
28 #include <kinputdialog.h>
30 #include <kabcpersistence.h>
31 #include <kdialogbase.h>
32 #include <klocale.h>
33 #include <kmenu.h>
34 #include <kmessagebox.h>
35 #include <klistviewsearchline.h>
37 #include "kopetecontactlist.h"
38 #include "kopeteglobal.h"
39 #include "kopeteuiglobal.h"
40 #include "kopeteprotocol.h"
41 #include "kopeteaccount.h"
42 #include "kopetestdaction.h"
43 #include "kopetechatsession.h"
44 #include "kopeteview.h"
45 #include "kopetemetacontact.h"
46 #include "kopeteprefs.h"
47 #include "metacontactselectorwidget.h"
49 //For the moving to another metacontact dialog
50 #include <qlabel.h>
51 #include <qimage.h>
52 #include <qmime.h>
53 #include <kvbox.h>
54 #include <klistview.h>
55 #include <qcheckbox.h>
58 namespace Kopete {
60 struct Contact::Private
62 public:
63 bool fileCapable;
65 OnlineStatus onlineStatus;
66 Account *account;
68 MetaContact *metaContact;
70 QString contactId;
71 QString icon;
73 QTime idleTimer;
74 unsigned long int idleTime;
76 Kopete::ContactProperty::Map properties;
80 Contact::Contact( Account *account, const QString &contactId,
81 MetaContact *parent, const QString &icon )
82 : QObject( parent )
84 d = new Private;
86 //kdDebug( 14010 ) << k_funcinfo << "Creating contact with id " << contactId << endl;
88 d->contactId = contactId;
89 d->metaContact = parent;
90 d->fileCapable = false;
91 d->account = account;
92 d->idleTime = 0;
93 d->icon = icon;
95 if ( account )
96 account->registerContact( this );
98 // Need to check this because myself() may have no parent
99 if( parent )
101 connect( parent, SIGNAL( aboutToSave( Kopete::MetaContact * ) ),
102 protocol(), SLOT( slotMetaContactAboutToSave( Kopete::MetaContact * ) ) );
104 parent->addContact( this );
107 connect( account, SIGNAL( isConnectedChanged() ), SLOT( slotAccountIsConnectedChanged() ) );
110 Contact::~Contact()
112 //kdDebug(14010) << k_funcinfo << endl;
113 emit( contactDestroyed( this ) );
114 delete d;
119 OnlineStatus Contact::onlineStatus() const
121 if ( this == account()->myself() || account()->isConnected() )
122 return d->onlineStatus;
123 else
124 return protocol()->accountOfflineStatus();
127 void Contact::setOnlineStatus( const OnlineStatus &status )
129 if( status == d->onlineStatus )
130 return;
132 OnlineStatus oldStatus = d->onlineStatus;
133 d->onlineStatus = status;
135 Kopete::Global::Properties *globalProps = Kopete::Global::Properties::self();
137 // Contact changed from Offline to another status
138 if( oldStatus.status() == OnlineStatus::Offline &&
139 status.status() != OnlineStatus::Offline )
141 setProperty( globalProps->onlineSince(), QDateTime::currentDateTime() );
142 /*kdDebug(14010) << k_funcinfo << "REMOVING lastSeen property for " <<
143 d->displayName << endl;*/
144 removeProperty( globalProps->lastSeen() );
146 else if( oldStatus.status() != OnlineStatus::Offline &&
147 oldStatus.status() != OnlineStatus::Unknown &&
148 status.status() == OnlineStatus::Offline ) // Contact went back offline
150 removeProperty( globalProps->onlineSince() );
151 /*kdDebug(14010) << k_funcinfo << "SETTING lastSeen property for " <<
152 d->displayName << endl;*/
153 setProperty( globalProps->lastSeen(), QDateTime::currentDateTime() );
156 if ( this == account()->myself() || account()->isConnected() )
157 emit onlineStatusChanged( this, status, oldStatus );
160 void Contact::slotAccountIsConnectedChanged()
162 if ( this == account()->myself() )
163 return;
165 if ( account()->isConnected() )
166 emit onlineStatusChanged( this, d->onlineStatus, protocol()->accountOfflineStatus() );
167 else
168 emit onlineStatusChanged( this, protocol()->accountOfflineStatus(), d->onlineStatus );
172 void Contact::sendFile( const KURL &, const QString &, uint )
174 kdWarning( 14010 ) << k_funcinfo << "Plugin "
175 << protocol()->pluginId() << " has enabled file sending, "
176 << "but didn't implement it!" << endl;
179 void Contact::slotAddContact()
181 if( metaContact() )
183 metaContact()->setTemporary( false );
184 ContactList::self()->addMetaContact( metaContact() );
188 KMenu* Contact::popupMenu( ChatSession *manager )
190 KMenu *menu = new KMenu();
192 QString titleText;
193 QString nick = property( Kopete::Global::Properties::self()->nickName() ).value().toString();
194 if( nick.isEmpty() )
195 titleText = QString::fromLatin1( "%1 (%2)" ).arg( contactId(), onlineStatus().description() );
196 else
197 titleText = QString::fromLatin1( "%1 <%2> (%3)" ).arg( nick, contactId(), onlineStatus().description() );
198 menu->addTitle( titleText );
200 #warning TODO
201 #if 0
203 if( metaContact() && metaContact()->isTemporary() && contactId() != account()->myself()->contactId() )
205 KAction *actionAddContact = new KAction( i18n( "&Add to Your Contact List" ), QString::fromLatin1( "bookmark_add" ),
206 0, this, SLOT( slotAddContact() ), menu, "actionAddContact" );
207 actionAddContact->plug( menu );
208 menu->addSeparator();
211 // FIXME: After KDE 3.2 we should make isReachable do the isConnected call so it can be removed here - Martijn
212 bool reach = account()->isConnected() && isReachable();
213 bool myself = (this == account()->myself());
215 KAction *actionSendMessage = KopeteStdAction::sendMessage( this, SLOT( sendMessage() ), menu, "actionSendMessage" );
216 actionSendMessage->setEnabled( reach && !myself );
217 actionSendMessage->plug( menu );
219 KAction *actionChat = KopeteStdAction::chat( this, SLOT( startChat() ), menu, "actionChat" );
220 actionChat->setEnabled( reach && !myself );
221 actionChat->plug( menu );
223 KAction *actionSendFile = KopeteStdAction::sendFile( this, SLOT( sendFile() ), menu, "actionSendFile" );
224 actionSendFile->setEnabled( reach && d->fileCapable && !myself );
225 actionSendFile->plug( menu );
227 // Protocol specific options will go below this separator
228 // through the use of the customContextMenuActions() function
230 // Get the custom actions from the protocols ( pure virtual function )
231 Q3PtrList<KAction> *customActions = customContextMenuActions( manager );
232 if( customActions && !customActions->isEmpty() )
234 menu->addSeparator();
236 for( KAction *a = customActions->first(); a; a = customActions->next() )
237 a->plug( menu );
239 delete customActions;
241 menu->addSeparator();
243 if( metaContact() && !metaContact()->isTemporary() )
244 KopeteStdAction::changeMetaContact( this, SLOT( changeMetaContact() ), menu, "actionChangeMetaContact" )->plug( menu );
246 KopeteStdAction::contactInfo( this, SLOT( slotUserInfo() ), menu, "actionUserInfo" )->plug( menu );
248 #if 0 //this is not fully implemented yet (and doesn't work). disable for now - Olivier 2005-01-11
249 if ( account()->isBlocked( d->contactId ) )
250 KopeteStdAction::unblockContact( this, SLOT( slotUnblock() ), menu, "actionUnblockContact" )->plug( menu );
251 else
252 KopeteStdAction::blockContact( this, SLOT( slotBlock() ), menu, "actionBlockContact" )->plug( menu );
253 #endif
255 if( metaContact() && !metaContact()->isTemporary() )
256 KopeteStdAction::deleteContact( this, SLOT( slotDelete() ), menu, "actionDeleteContact" )->plug( menu );
257 #endif
258 return menu;
261 void Contact::changeMetaContact()
263 KDialogBase *moveDialog = new KDialogBase( Kopete::UI::Global::mainWidget(), "moveDialog", true, i18n( "Move Contact" ),
264 KDialogBase::Ok | KDialogBase::Cancel, KDialogBase::Ok, true );
266 KVBox *w = new KVBox( moveDialog );
267 w->setSpacing( KDialog::spacingHint() );
268 Kopete::UI::MetaContactSelectorWidget *selector = new Kopete::UI::MetaContactSelectorWidget(w);
269 selector->setLabelMessage(i18n( "Select the meta contact to which you want to move this contact:" ));
270 // exclude this metacontact as a target metacontact for the move
271 selector->excludeMetaContact( metaContact() );
272 QCheckBox *chkCreateNew = new QCheckBox( i18n( "Create a new metacontact for this contact" ), w );
273 chkCreateNew ->setWhatsThis( i18n( "If you select this option, a new metacontact will be created in the top-level group "
274 "with the name of this contact and the contact will be moved to it." ) );
275 QObject::connect( chkCreateNew , SIGNAL( toggled(bool) ) , selector , SLOT ( setDisabled(bool) ) ) ;
277 moveDialog->setMainWidget(w);
278 if( moveDialog->exec() == QDialog::Accepted )
280 Kopete::MetaContact *mc = selector->metaContact();
281 if(chkCreateNew->isChecked())
283 mc=new Kopete::MetaContact();
284 Kopete::ContactList::self()->addMetaContact(mc);
286 if( mc )
288 setMetaContact( mc );
292 moveDialog->deleteLater();
295 void Contact::setMetaContact( MetaContact *m )
297 MetaContact *old = d->metaContact;
298 if(old==m) //that make no sens
299 return;
301 if( old )
303 int result=KMessageBox::No;
304 if( old->isTemporary() )
305 result=KMessageBox::Yes;
306 else if( old->contacts().count()==1 )
307 { //only one contact, including this one, that mean the contact will be empty efter the move
308 result = KMessageBox::questionYesNoCancel( Kopete::UI::Global::mainWidget(), i18n( "You are moving the contact `%1' to the meta contact `%2'.\n"
309 "`%3' will be empty afterwards. Do you want to delete this contact?" )
310 .arg(contactId(), m ? m->displayName() : QString::null, old->displayName())
311 , i18n( "Move Contact" ), KStdGuiItem::del(), i18n( "&Keep" ) , QString::fromLatin1("delete_old_contact_when_move") );
312 if(result==KMessageBox::Cancel)
313 return;
315 old->removeContact( this );
316 disconnect( old, SIGNAL( aboutToSave( Kopete::MetaContact * ) ),
317 protocol(), SLOT( slotMetaContactAboutToSave( Kopete::MetaContact * ) ) );
319 if(result==KMessageBox::Yes)
321 //remove the old metacontact. (this delete the MC)
322 ContactList::self()->removeMetaContact(old);
324 else
326 d->metaContact = m; //i am forced to do that now if i want the next line works
327 //remove cached data for this protocol which will not be removed since we disconnected
328 protocol()->slotMetaContactAboutToSave( old );
332 d->metaContact = m;
334 if( m )
336 m->addContact( this );
337 m->insertChild( this );
338 // it is necessary to call this write here, because MetaContact::addContact() does not differentiate
339 // between adding completely new contacts (which should be written to kabc) and restoring upon restart
340 // (where no write is needed).
341 KABCPersistence::self()->write( m );
342 connect( d->metaContact, SIGNAL( aboutToSave( Kopete::MetaContact * ) ),
343 protocol(), SLOT( slotMetaContactAboutToSave( Kopete::MetaContact * ) ) );
345 sync();
348 void Contact::serialize( QMap<QString, QString> &/*serializedData*/,
349 QMap<QString, QString> & /* addressBookData */ )
354 void Contact::serializeProperties(QMap<QString, QString> &serializedData)
357 Kopete::ContactProperty::Map::ConstIterator it;// = d->properties.ConstIterator;
358 for (it=d->properties.begin(); it != d->properties.end(); ++it)
360 if (!it.data().tmpl().persistent())
361 continue;
363 QVariant val = it.data().value();
364 QString key = QString::fromLatin1("prop_%1_%2").arg(QString::fromLatin1(val.typeName()), it.key());
366 serializedData[key] = val.toString();
368 } // end for()
369 } // end serializeProperties()
371 void Contact::deserializeProperties(
372 QMap<QString, QString> &serializedData )
374 QMap<QString, QString>::ConstIterator it;
375 for ( it=serializedData.begin(); it != serializedData.end(); ++it )
377 QString key = it.key();
379 if ( !key.startsWith( QString::fromLatin1("prop_") ) ) // avoid parsing other serialized data
380 continue;
382 QStringList keyList = QStringList::split( QChar('_'), key, false );
383 if( keyList.count() < 3 ) // invalid key, not enough parts in string "prop_X_Y"
384 continue;
386 key = keyList[2]; // overwrite key var with the real key name this property has
387 QString type( keyList[1] ); // needed for QVariant casting
389 QVariant variant( it.data() );
390 if( !variant.cast(QVariant::nameToType(type.toLatin1())) )
392 kdDebug(14010) << k_funcinfo <<
393 "Casting QVariant to needed type FAILED" <<
394 "key=" << key << ", type=" << type << endl;
395 continue;
398 Kopete::ContactPropertyTmpl tmpl = Kopete::Global::Properties::self()->tmpl(key);
399 if( tmpl.isNull() )
401 kdDebug( 14010 ) << k_funcinfo << "no ContactPropertyTmpl defined for" \
402 " key " << key << ", cannot restore persistent property" << endl;
403 continue;
406 setProperty(tmpl, variant);
407 } // end for()
411 bool Contact::isReachable()
413 // The default implementation returns false when offline and true
414 // otherwise. Subclass if you need more control over the process.
415 return onlineStatus().status() != OnlineStatus::Offline;
419 void Contact::startChat()
421 KopeteView *v=manager( CanCreate )->view(true, QString::fromLatin1("kopete_chatwindow") );
422 if(v)
423 v->raise(true);
426 void Contact::sendMessage()
428 KopeteView *v=manager( CanCreate )->view(true, QString::fromLatin1("kopete_emailwindow") );
429 if(v)
430 v->raise(true);
433 void Contact::execute()
435 // FIXME: After KDE 3.2 remove the isConnected check and move it to isReachable - Martijn
436 if ( account()->isConnected() && isReachable() )
438 KopeteView *v=manager( CanCreate )->view(true, KopetePrefs::prefs()->interfacePreference() );
439 if(v)
440 v->raise(true);
442 else
444 KMessageBox::queuedMessageBox( Kopete::UI::Global::mainWidget(), KMessageBox::Sorry,
445 i18n( "This user is not reachable at the moment. Please try a protocol that supports offline sending, or wait "
446 "until this user comes online." ), i18n( "User is Not Reachable" ) );
450 void Contact::slotDelete()
452 if ( KMessageBox::warningContinueCancel( Kopete::UI::Global::mainWidget(),
453 i18n( "Are you sure you want to remove the contact '%1' from your contact list?" ).
454 arg( d->contactId ), i18n( "Remove Contact" ), KGuiItem(i18n("Remove"), QString::fromLatin1("editdelete") ),
455 QString::fromLatin1("askRemoveContact"), KMessageBox::Notify | KMessageBox::Dangerous )
456 == KMessageBox::Continue )
458 deleteContact();
462 void Contact::deleteContact()
464 // Default implementation simply deletes the contact
465 deleteLater();
469 MetaContact * Contact::metaContact() const
471 return d->metaContact;
474 QString Contact::contactId() const
476 return d->contactId;
479 Protocol * Contact::protocol() const
481 return d->account ? d->account->protocol() : 0L;
484 Account * Contact::account() const
486 return d->account;
491 void Contact::sync(unsigned int)
493 /* Default implementation does nothing */
496 QString& Contact::icon() const
498 return d->icon;
501 void Contact::setIcon( const QString& icon )
503 d->icon = icon;
504 return;
507 QList<KAction *> *Contact::customContextMenuActions()
509 return 0L;
512 QList<KAction*> *Contact::customContextMenuActions( ChatSession * /* manager */ )
514 return customContextMenuActions();
518 bool Contact::isOnline() const
520 return onlineStatus().isDefinitelyOnline();
524 bool Contact::isFileCapable() const
526 return d->fileCapable;
529 void Contact::setFileCapable( bool filecap )
531 d->fileCapable = filecap;
535 bool Contact::canAcceptFiles() const
537 return isOnline() && d->fileCapable;
540 unsigned long int Contact::idleTime() const
542 if(d->idleTime==0)
543 return 0;
545 return d->idleTime+(d->idleTimer.elapsed()/1000);
548 void Contact::setIdleTime( unsigned long int t )
550 bool idleChanged = false;
551 if(d->idleTime != t)
552 idleChanged = true;
553 d->idleTime=t;
554 if(t > 0)
555 d->idleTimer.start();
556 //FIXME: if t == 0, idleTime() will now return garbage
557 // else
558 // d->idleTimer.stop();
559 if(idleChanged)
560 emit idleStateChanged(this);
564 QStringList Contact::properties() const
566 return d->properties.keys();
569 bool Contact::hasProperty(const QString &key) const
571 return d->properties.contains(key);
574 const ContactProperty &Contact::property(const QString &key) const
576 if(hasProperty(key))
577 return d->properties[key];
578 else
579 return Kopete::ContactProperty::null;
582 const Kopete::ContactProperty &Contact::property(
583 const Kopete::ContactPropertyTmpl &tmpl) const
585 if(hasProperty(tmpl.key()))
586 return d->properties[tmpl.key()];
587 else
588 return Kopete::ContactProperty::null;
592 void Contact::setProperty(const Kopete::ContactPropertyTmpl &tmpl,
593 const QVariant &value)
595 if(tmpl.isNull() || tmpl.key().isEmpty())
597 kdDebug(14000) << k_funcinfo <<
598 "No valid template for property passed!" << endl;
599 return;
602 if(value.isNull() || value.canCast(QVariant::String) && value.toString().isEmpty())
604 removeProperty(tmpl);
606 else
608 QVariant oldValue = property(tmpl.key()).value();
610 if(oldValue != value)
612 Kopete::ContactProperty prop(tmpl, value);
613 d->properties.insert(tmpl.key(), prop, true);
615 emit propertyChanged(this, tmpl.key(), oldValue, value);
620 void Contact::removeProperty(const Kopete::ContactPropertyTmpl &tmpl)
622 if(!tmpl.isNull() && !tmpl.key().isEmpty())
625 QVariant oldValue = property(tmpl.key()).value();
626 d->properties.remove(tmpl.key());
627 emit propertyChanged(this, tmpl.key(), oldValue, QVariant());
632 QString Contact::toolTip() const
634 Kopete::ContactProperty p;
635 QString tip;
636 QStringList shownProps = KopetePrefs::prefs()->toolTipContents();
638 // --------------------------------------------------------------------------
639 // Fixed part of tooltip
641 QString iconName = QString::fromLatin1("kopete-contact-icon:%1:%2:%3")
642 .arg( KURL::encode_string( protocol()->pluginId() ),
643 KURL::encode_string( account()->accountId() ),
644 KURL::encode_string( contactId() ) );
646 // TODO: the nickname should be a configurable properties, like others. -Olivier
647 QString nick = property( Kopete::Global::Properties::self()->nickName() ).value().toString();
648 if ( nick.isEmpty() )
650 tip = i18n( "<b>DISPLAY NAME</b><br><img src=\"%2\">&nbsp;CONTACT STATUS",
651 "<b><nobr>%3</nobr></b><br><img src=\"%2\">&nbsp;%1" ).
652 arg( Kopete::Message::escape( onlineStatus().description() ), iconName,
653 Kopete::Message::escape( d->contactId ) );
655 else
657 tip = i18n( "<b>DISPLAY NAME</b> (CONTACT ID)<br><img src=\"%2\">&nbsp;CONTACT STATUS",
658 "<nobr><b>%4</b> (%3)</nobr><br><img src=\"%2\">&nbsp;%1" ).
659 arg( Kopete::Message::escape( onlineStatus().description() ), iconName,
660 Kopete::Message::escape( contactId() ),
661 Kopete::Message::escape( nick ) );
664 // --------------------------------------------------------------------------
665 // Configurable part of tooltip
667 for(QStringList::Iterator it=shownProps.begin(); it!=shownProps.end(); ++it)
669 if((*it) == QString::fromLatin1("FormattedName"))
671 QString name = formattedName();
672 if(!name.isEmpty())
674 tip += i18n("<br><b>Full Name:</b>&nbsp;FORMATTED NAME",
675 "<br><b>Full Name:</b>&nbsp;<nobr>%1</nobr>").arg(Q3StyleSheet::escape(name));
678 else if ((*it) == QString::fromLatin1("FormattedIdleTime"))
680 QString time = formattedIdleTime();
681 if(!time.isEmpty())
683 tip += i18n("<br><b>Idle:</b>&nbsp;FORMATTED IDLE TIME",
684 "<br><b>Idle:</b>&nbsp;<nobr>%1</nobr>").arg(time);
687 else if ((*it) == QString::fromLatin1("homePage"))
689 QString url = property(*it).value().toString();
690 if(!url.isEmpty())
692 tip += i18n("<br><b>Home Page:</b>&nbsp;FORMATTED URL",
693 "<br><b>Home Page:</b>&nbsp;<a href=\"%1\"><nobr>%2</nobr></a>").
694 arg( KURL::encode_string( url ), Kopete::Message::escape( Q3StyleSheet::escape(url) ) );
697 else if ((*it) == QString::fromLatin1("awayMessage"))
699 QString awaymsg = property(*it).value().toString();
700 if(!awaymsg.isEmpty())
702 tip += i18n("<br><b>Away Message:</b>&nbsp;FORMATTED AWAY MESSAGE",
703 "<br><b>Away&nbsp;Message:</b>&nbsp;%1").arg ( Kopete::Message::escape(awaymsg) );
706 else
708 p = property(*it);
709 if(!p.isNull())
711 QVariant val = p.value();
712 QString valueText;
714 switch(val.type())
716 case QVariant::DateTime:
717 valueText = KGlobal::locale()->formatDateTime(val.toDateTime());
718 valueText = Kopete::Message::escape( valueText );
719 break;
720 case QVariant::Date:
721 valueText = KGlobal::locale()->formatDate(val.toDate());
722 valueText = Kopete::Message::escape( valueText );
723 break;
724 case QVariant::Time:
725 valueText = KGlobal::locale()->formatTime(val.toTime());
726 valueText = Kopete::Message::escape( valueText );
727 break;
728 default:
729 if( p.isRichText() )
731 valueText = val.toString();
733 else
735 valueText = Kopete::Message::escape( val.toString() );
739 tip += i18n("<br><b>PROPERTY LABEL:</b>&nbsp;PROPERTY VALUE",
740 "<br><nobr><b>%2:</b></nobr>&nbsp;%1").
741 arg( valueText, Q3StyleSheet::escape(p.tmpl().label()) );
746 return tip;
749 QString Kopete::Contact::formattedName() const
751 if( hasProperty(QString::fromLatin1("FormattedName")) )
752 return property(QString::fromLatin1("FormattedName")).value().toString();
754 QString ret;
755 Kopete::ContactProperty first, last;
757 first = property(QString::fromLatin1("firstName"));
758 last = property(QString::fromLatin1("lastName"));
759 if(!first.isNull())
761 if(!last.isNull()) // contact has both first and last name
763 ret = i18n("firstName lastName", "%2 %1")
764 .arg(last.value().toString())
765 .arg(first.value().toString());
767 else // only first name set
769 ret = first.value().toString();
772 else if(!last.isNull()) // only last name set
774 ret = last.value().toString();
777 return ret;
780 QString Kopete::Contact::formattedIdleTime() const
782 QString ret;
783 unsigned long int leftTime = idleTime();
785 if ( leftTime > 0 )
786 { // FIXME: duplicated from code in kopetecontactlistview.cpp
787 unsigned long int days, hours, mins, secs;
789 days = leftTime / ( 60*60*24 );
790 leftTime = leftTime % ( 60*60*24 );
791 hours = leftTime / ( 60*60 );
792 leftTime = leftTime % ( 60*60 );
793 mins = leftTime / 60;
794 secs = leftTime % 60;
796 if ( days != 0 )
798 ret = i18n( "<days>d <hours>h <minutes>m <seconds>s",
799 "%4d %3h %2m %1s" )
800 .arg( secs )
801 .arg( mins )
802 .arg( hours )
803 .arg( days );
805 else if ( hours != 0 )
807 ret = i18n( "<hours>h <minutes>m <seconds>s", "%3h %2m %1s" )
808 .arg( secs )
809 .arg( mins )
810 .arg( hours );
812 else
814 ret = i18n( "<minutes>m <seconds>s", "%2m %1s" )
815 .arg( secs )
816 .arg( mins );
819 return ret;
823 void Kopete::Contact::slotBlock()
825 account()->block( d->contactId );
828 void Kopete::Contact::slotUnblock()
830 account()->unblock( d->contactId );
833 void Kopete::Contact::setNickName( const QString &name )
835 setProperty( Kopete::Global::Properties::self()->nickName(), name );
838 QString Kopete::Contact::nickName() const
840 QString nick = property( Kopete::Global::Properties::self()->nickName() ).value().toString();
841 if( !nick.isEmpty() )
842 return nick;
844 return contactId();
847 void Contact::virtual_hook( uint , void * )
851 } //END namespace Kopete
854 #include "kopetecontact.moc"