/* channellist.cpp - IRC Channel Search Widget Copyright (c) 2004 by Jason Keirstead 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 "channellist.h" #include "kircengine.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include class ChannelListItem : public TDEListViewItem { public: ChannelListItem( TDEListView *parent, TQString arg1, TQString arg2, TQString arg3 ); virtual int compare( TQListViewItem *i, int col, bool ascending ) const; virtual void paintCell( TQPainter *p, const TQColorGroup &cg, int column, int width, int align ); private: TDEListView *parentList; }; ChannelListItem::ChannelListItem( TDEListView *parent, TQString arg1, TQString arg2, TQString arg3 ) : TDEListViewItem( parent, parent->lastItem() ), parentList( parent ) { setText(0, arg1); setText(1, arg2); setText(2, arg3); } int ChannelListItem::compare( TQListViewItem *i, int col, bool ascending ) const { if( col == 1 ) { if( text(1).toUInt() < i->text(1).toUInt() ) return -1; else if ( text(1).toUInt() == i->text(1).toUInt() ) return 0; else return 1; } else return TQListViewItem::compare( i, col, ascending ); } void ChannelListItem::paintCell( TQPainter *p, const TQColorGroup &cg, int column, int width, int align ) { TQPixmap back( width, height() ); TQPainter paint( &back ); //TDEListViewItem::paintCell( &paint, cg, column, width, align ); // PASTED FROM KLISTVIEWITEM: // set the alternate cell background colour if necessary TQColorGroup _cg = cg; if (isAlternate()) if (listView()->viewport()->backgroundMode()==TQt::FixedColor) _cg.setColor(TQColorGroup::Background, static_cast< TDEListView* >(listView())->alternateBackground()); else _cg.setColor(TQColorGroup::Base, static_cast< TDEListView* >(listView())->alternateBackground()); // PASTED FROM TQLISTVIEWITEM { TQPainter *p = &paint; TQListView *lv = listView(); if ( !lv ) return; TQFontMetrics fm( p->fontMetrics() ); // any text we render is done by the Components, not by this class, so make sure we've nothing to write TQString t; // removed text truncating code from TQt - we do that differently, further on int marg = lv->itemMargin(); int r = marg; // const TQPixmap * icon = pixmap( column ); const BackgroundMode bgmode = lv->viewport()->backgroundMode(); const TQColorGroup::ColorRole crole = TQPalette::backgroundRoleFromMode( bgmode ); if ( _cg.brush( crole ) != lv->colorGroup().brush( crole ) ) p->fillRect( 0, 0, width, height(), _cg.brush( crole ) ); else { // all copied from TQListView::paintEmptyArea //lv->paintEmptyArea( p, TQRect( 0, 0, width, height() ) ); TQStyleOption opt( lv->sortColumn(), 0 ); // ### hack; in 3.1, add a property in TQListView and TQHeader TQStyle::SFlags how = TQStyle::Style_Default; if ( lv->isEnabled() ) how |= TQStyle::Style_Enabled; lv->style().drawComplexControl( TQStyle::CC_ListView, p, lv, TQRect( 0, 0, width, height() ), lv->colorGroup(), how, TQStyle::SC_ListView, TQStyle::SC_None, opt ); } if ( isSelected() && (column == 0 || lv->allColumnsShowFocus()) ) { p->fillRect( r - marg, 0, width - r + marg, height(), _cg.brush( TQColorGroup::Highlight ) ); // removed text pen setting code from TQt } // removed icon drawing code from TQt // draw the tree gubbins if ( multiLinesEnabled() && column == 0 && isOpen() && childCount() ) { int textheight = fm.size( align, t ).height() + 2 * lv->itemMargin(); textheight = TQMAX( textheight, TQApplication::globalStrut().height() ); if ( textheight % 2 > 0 ) textheight++; if ( textheight < height() ) { int w = lv->treeStepSize() / 2; lv->style().drawComplexControl( TQStyle::CC_ListView, p, lv, TQRect( 0, textheight, w + 1, height() - textheight + 1 ), _cg, lv->isEnabled() ? TQStyle::Style_Enabled : TQStyle::Style_Default, TQStyle::SC_ListViewExpand, (uint)TQStyle::SC_All, TQStyleOption( this ) ); } } } // END OF PASTE //do you see a better way to tell the TextComponent we are selected ? - Olivier 2004-09-02 if ( isSelected() ) _cg.setColor(TQColorGroup::Text , _cg.highlightedText() ); TQSimpleRichText myrichtext( text(column), paint.font() ); myrichtext.draw( &paint, 0, 0, paint.window(), _cg ); paint.end(); p->drawPixmap( 0, 0, back ); } ChannelList::ChannelList( TQWidget* parent, KIRC::Engine *engine ) : TQWidget( parent ), m_engine( engine ) { ChannelListLayout = new TQVBoxLayout( this, 11, 6, "ChannelListLayout"); layout72_2 = new TQHBoxLayout( 0, 0, 6, "layout72_2"); textLabel1_2 = new TQLabel( this, "textLabel1_2" ); layout72_2->addWidget( textLabel1_2 ); channelSearch = new TQLineEdit( this, "channelSearch" ); layout72_2->addWidget( channelSearch ); numUsers = new TQSpinBox( 0, 32767, 1, this, "num_users" ); numUsers->setSuffix( i18n(" members") ); layout72_2->addWidget( numUsers ); mSearchButton = new TQPushButton( this, "mSearchButton" ); layout72_2->addWidget( mSearchButton ); ChannelListLayout->addLayout( layout72_2 ); mChannelList = new TDEListView( this, "mChannelList" ); mChannelList->addColumn( i18n( "Channel" ) ); mChannelList->addColumn( i18n( "Users" ) ); mChannelList->header()->setResizeEnabled( FALSE, mChannelList->header()->count() - 1 ); mChannelList->addColumn( i18n( "Topic" ) ); mChannelList->setAllColumnsShowFocus( TRUE ); mChannelList->setShowSortIndicator( TRUE ); ChannelListLayout->addWidget( mChannelList ); clearWState( WState_Polished ); textLabel1_2->setText( i18n( "Search for:" ) ); TQToolTip::add( textLabel1_2, i18n( "You may search for channels on the IRC server for a text string entered here." ) ); TQToolTip::add( numUsers, i18n( "Channels returned must have at least this many members." ) ); TQWhatsThis::add( numUsers, i18n( "Channels returned must have at least this many members." ) ); TQWhatsThis::add( textLabel1_2, i18n( "You may search for channels on the IRC server for a text string entered here. For instance, you may type 'linux' to find channels that have something to do with linux." ) ); TQToolTip::add( channelSearch, i18n( "You may search for channels on the IRC server for a text string entered here." ) ); TQWhatsThis::add( channelSearch, i18n( "You may search for channels on the IRC server for a text string entered here. For instance, you may type 'linux' to find channels that have something to do with linux." ) ); mSearchButton->setText( i18n( "S&earch" ) ); TQToolTip::add( mSearchButton, i18n( "Perform a channel search." ) ); TQWhatsThis::add( mSearchButton, i18n( "Perform a channel search. Please be patient, as this can be slow depending on the number of channels on the server." ) ); TQToolTip::add( mChannelList, i18n( "Double click on a channel to select it." ) ); mChannelList->header()->setLabel( 0, i18n( "Channel" ) ); mChannelList->header()->setLabel( 1, i18n( "Users" ) ); mChannelList->header()->setLabel( 2, i18n( "Topic" ) ); // signals and slots connections connect( mChannelList, TQT_SIGNAL( doubleClicked(TQListViewItem*) ), this, TQT_SLOT( slotItemDoubleClicked(TQListViewItem*) ) ); connect( mSearchButton, TQT_SIGNAL( clicked() ), this, TQT_SLOT( search() ) ); connect( mChannelList, TQT_SIGNAL( selectionChanged( TQListViewItem*) ), this, TQT_SLOT( slotItemSelected( TQListViewItem *) ) ); connect( m_engine, TQT_SIGNAL( incomingListedChan( const TQString &, uint, const TQString & ) ), this, TQT_SLOT( slotChannelListed( const TQString &, uint, const TQString & ) ) ); connect( m_engine, TQT_SIGNAL( incomingEndOfList() ), this, TQT_SLOT( slotListEnd() ) ); connect( m_engine, TQT_SIGNAL( statusChanged(KIRC::Engine::Status) ), this, TQT_SLOT( slotStatusChanged(KIRC::Engine::Status) ) ); show(); } void ChannelList::slotItemDoubleClicked( TQListViewItem *i ) { emit channelDoubleClicked( i->text(0) ); } void ChannelList::slotItemSelected( TQListViewItem *i ) { emit channelSelected( i->text(0) ); } void ChannelList::slotStatusChanged(KIRC::Engine::Status newStatus) { switch(newStatus) { case KIRC::Engine::Connected: this->reset(); break; case KIRC::Engine::Disconnected: if (mSearching) { KMessageBox::queuedMessageBox( this, KMessageBox::Error, i18n("You have been disconnected from the IRC server."), i18n("Disconnected"), 0 ); } slotListEnd(); break; default: break; } } void ChannelList::reset() { channelCache.clear(); clear(); } void ChannelList::clear() { mChannelList->clear(); channelSearch->clear(); channelSearch->setFocus(); } void ChannelList::search() { if( m_engine->isConnected() || !channelCache.isEmpty() ) { mChannelList->clear(); mChannelList->setSorting( -1 ); mSearchButton->setEnabled(false); mSearch = channelSearch->text(); mSearching = true; mUsers = numUsers->value(); if( channelCache.isEmpty() ) m_engine->list(); else { cacheIterator = channelCache.begin(); slotSearchCache(); } } else { KMessageBox::queuedMessageBox( this, KMessageBox::Error, i18n("You must be connected to the IRC server to perform a channel listing."), i18n("Not Connected"), 0 ); } } void ChannelList::slotChannelListed( const TQString &channel, uint users, const TQString &topic ) { checkSearchResult( channel, users, topic ); channelCache.insert( channel, TQPair< uint, TQString >( users, topic ) ); } void ChannelList::checkSearchResult( const TQString &channel, uint users, const TQString &topic ) { if( ( mUsers == 0 || mUsers <= users ) && ( mSearch.isEmpty() || channel.contains( mSearch, false ) || topic.contains( mSearch, false ) ) ) { new ChannelListItem( mChannelList, channel, TQString::number(users), topic ); } } void ChannelList::slotSearchCache() { if( cacheIterator != channelCache.end() ) { checkSearchResult( cacheIterator.key(), cacheIterator.data().first, cacheIterator.data().second ); ++cacheIterator; TQTimer::singleShot( 0, this, TQT_SLOT( slotSearchCache() ) ); } else { slotListEnd(); } } void ChannelList::slotListEnd() { mChannelList->setSorting(0, true); mSearchButton->setEnabled(true); mSearching = false; } #include "channellist.moc"