/* chatmemberslistwidget.cpp - Chat Members List Widget Copyright (c) 2004 by Richard Smith Kopete (c) 2002-2004 by the Kopete developers ************************************************************************* * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ************************************************************************* */ #include "chatmemberslistwidget.h" #include "kopetechatsession.h" #include "kopetecontact.h" #include "kopeteonlinestatus.h" #include "kopeteglobal.h" #include "kopeteprotocol.h" #include "kopeteaccount.h" #include "kopetemetacontact.h" #include #include #include #include #include #include #include #include //BEGIN ChatMembersListWidget::ToolTip class ChatMembersListWidget::ToolTip : public TQToolTip { public: ToolTip( TDEListView *parent ) : TQToolTip( parent->viewport() ), m_listView ( parent ) { } virtual ~ToolTip() { remove( m_listView->viewport() ); } void maybeTip( const TQPoint &pos ) { if( TQListViewItem *item = m_listView->itemAt( pos ) ) { TQRect itemRect = m_listView->itemRect( item ); if( itemRect.contains( pos ) ) tip( itemRect, static_cast( item )->contact()->toolTip() ); } } private: TDEListView *m_listView; }; //END ChatMembersListWidget::ToolTip //BEGIN ChatMembersListWidget::ContactItem ChatMembersListWidget::ContactItem::ContactItem( ChatMembersListWidget *parent, Kopete::Contact *contact ) : TDEListViewItem( parent ), m_contact( contact ) { TQString nick = m_contact->property(Kopete::Global::Properties::self()->nickName().key()).value().toString(); if ( nick.isEmpty() ) nick = m_contact->contactId(); setText( 0, nick ); setDragEnabled(true); connect( m_contact, TQT_SIGNAL( propertyChanged( Kopete::Contact *, const TQString &, const TQVariant &, const TQVariant & ) ), this, TQT_SLOT( slotPropertyChanged( Kopete::Contact *, const TQString &, const TQVariant &, const TQVariant & ) ) ) ; setStatus( parent->session()->contactOnlineStatus(m_contact) ); reposition(); } void ChatMembersListWidget::ContactItem::slotPropertyChanged( Kopete::Contact*, const TQString &key, const TQVariant&, const TQVariant &newValue ) { if ( key == Kopete::Global::Properties::self()->nickName().key() ) { setText( 0, newValue.toString() ); reposition(); } } void ChatMembersListWidget::ContactItem::setStatus( const Kopete::OnlineStatus &status ) { setPixmap( 0, status.iconFor( m_contact ) ); reposition(); } void ChatMembersListWidget::ContactItem::reposition() { // TQt's listview sorting is pathetic - it's impossible to reposition a single item // when its key changes, without re-sorting the whole list. Plus, the whole list gets // re-sorted whenever an item is added/removed. So, we do manual sorting. // In particular, this makes adding N items O(N^2) not O(N^2 log N). Kopete::ChatSession *session = static_cast( listView() )->session(); int ourWeight = session->contactOnlineStatus(m_contact).weight(); TQListViewItem *after = 0; for ( TQListViewItem *it = TDEListViewItem::listView()->firstChild(); it; it = it->nextSibling() ) { ChatMembersListWidget::ContactItem *item = static_cast(it); int theirWeight = session->contactOnlineStatus(item->m_contact).weight(); if( theirWeight < ourWeight || (theirWeight == ourWeight && item->text(0).localeAwareCompare( text(0) ) > 0 ) ) { break; } after = it; } moveItem( after ); } //END ChatMembersListWidget::ContactItem //BEGIN ChatMembersListWidget ChatMembersListWidget::ChatMembersListWidget( Kopete::ChatSession *session, TQWidget *parent, const char *name ) : TDEListView( parent, name ), m_session( session ) { // use our own custom tooltips setShowToolTips( false ); m_toolTip = new ToolTip( this ); // set up display: no header setAllColumnsShowFocus( true ); addColumn( TQString(), -1 ); header()->setStretchEnabled( true, 0 ); header()->hide(); // list is sorted by us, not by TQt setSorting( -1 ); // add chat members slotContactAdded( session->myself() ); for ( TQPtrListIterator it( session->members() ); it.current(); ++it ) slotContactAdded( *it ); connect( this, TQT_SIGNAL( contextMenu( TDEListView*, TQListViewItem *, const TQPoint &) ), TQT_SLOT( slotContextMenu(TDEListView*, TQListViewItem *, const TQPoint & ) ) ); connect( this, TQT_SIGNAL( executed( TQListViewItem* ) ), TQT_SLOT( slotExecute( TQListViewItem * ) ) ); connect( session, TQT_SIGNAL( contactAdded(const Kopete::Contact*, bool) ), this, TQT_SLOT( slotContactAdded(const Kopete::Contact*) ) ); connect( session, TQT_SIGNAL( contactRemoved(const Kopete::Contact*, const TQString&, Kopete::Message::MessageFormat, bool) ), this, TQT_SLOT( slotContactRemoved(const Kopete::Contact*) ) ); connect( session, TQT_SIGNAL( onlineStatusChanged( Kopete::Contact *, const Kopete::OnlineStatus & , const Kopete::OnlineStatus &) ), this, TQT_SLOT( slotContactStatusChanged( Kopete::Contact *, const Kopete::OnlineStatus & ) ) ); } ChatMembersListWidget::~ChatMembersListWidget() { } void ChatMembersListWidget::slotContextMenu( TDEListView*, TQListViewItem *item, const TQPoint &point ) { if ( ContactItem *contactItem = dynamic_cast(item) ) { TDEPopupMenu *p = contactItem->contact()->popupMenu( session() ); connect( p, TQT_SIGNAL( aboutToHide() ), p, TQT_SLOT( deleteLater() ) ); p->popup( point ); } } void ChatMembersListWidget::slotContactAdded( const Kopete::Contact *contact ) { if ( !m_members.contains( contact ) ) m_members.insert( contact, new ContactItem( this, const_cast( contact ) ) ); } void ChatMembersListWidget::slotContactRemoved( const Kopete::Contact *contact ) { kdDebug(14000) << k_funcinfo << endl; if ( m_members.contains( contact ) && contact != session()->myself() ) { delete m_members[ contact ]; m_members.remove( contact ); } } void ChatMembersListWidget::slotContactStatusChanged( Kopete::Contact *contact, const Kopete::OnlineStatus &status ) { if ( m_members.contains( contact ) ) m_members[contact]->setStatus( status ); } void ChatMembersListWidget::slotExecute( TQListViewItem *item ) { if ( ContactItem *contactItem = dynamic_cast(item ) ) { Kopete::Contact *contact=contactItem->contact(); if(!contact || contact == contact->account()->myself()) return; contact->execute(); } } TQDragObject *ChatMembersListWidget::dragObject() { TQListViewItem *currentLVI = currentItem(); if( !currentLVI ) return 0L; ContactItem *lvi = dynamic_cast( currentLVI ); if( !lvi ) return 0L; Kopete::Contact *c = lvi->contact(); KMultipleDrag *drag = new KMultipleDrag( this ); drag->addDragObject( new TQStoredDrag("application/x-qlistviewitem", 0L ) ); TQStoredDrag *d = new TQStoredDrag("kopete/x-contact", 0L ); d->setEncodedData( TQString( c->protocol()->pluginId()+TQChar( 0xE000 )+c->account()->accountId()+TQChar( 0xE000 )+ c->contactId() ).utf8() ); drag->addDragObject( d ); TDEABC::Addressee address = TDEABC::StdAddressBook::self()->findByUid(c->metaContact()->metaContactId()); if( !address.isEmpty() ) { drag->addDragObject( new TQTextDrag( address.fullEmail(), 0L ) ); TDEABC::VCardConverter converter; TQString vcard = converter.createVCard( address ); if( !vcard.isNull() ) { TQStoredDrag *vcardDrag = new TQStoredDrag("text/x-vcard", 0L ); vcardDrag->setEncodedData( vcard.utf8() ); drag->addDragObject( vcardDrag ); } } drag->setPixmap( c->onlineStatus().iconFor(c, 12) ); return drag; } //END ChatMembersListWidget #include "chatmemberslistwidget.moc" // vim: set noet ts=4 sts=4 sw=4: