You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdenetwork/kopete/protocols/irc/ui/channellist.cpp

347 lines
11 KiB

/*
channellist.cpp - IRC Channel Search Widget
Copyright (c) 2004 by Jason Keirstead <jason@keirstead.org>
Kopete (c) 2002-2004 by the Kopete developers <kopete-devel@kde.org>
*************************************************************************
* *
* 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 <klocale.h>
#include <kmessagebox.h>
#include <tqvariant.h>
#include <tqlabel.h>
#include <tqpainter.h>
#include <tqapplication.h>
#include <tqsimplerichtext.h>
#include <tqstyle.h>
#include <tqlineedit.h>
#include <tqpushbutton.h>
#include <tqheader.h>
#include <klistview.h>
#include <tqlayout.h>
#include <tqtooltip.h>
#include <tqtimer.h>
#include <tqspinbox.h>
#include <tqwhatsthis.h>
class ChannelListItem : public KListViewItem
{
public:
ChannelListItem( KListView *tqparent, 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:
KListView *parentList;
};
ChannelListItem::ChannelListItem( KListView *tqparent, TQString arg1, TQString arg2, TQString arg3 ) :
KListViewItem( tqparent, tqparent->lastItem() ), parentList( tqparent )
{
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 );
//KListViewItem::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< KListView* >(listView())->alternateBackground());
else
_cg.setColor(TQColorGroup::Base, static_cast< KListView* >(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->tqcolorGroup().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->tqstyle().tqdrawComplexControl( TQStyle::CC_ListView,
p, lv, TQRect( 0, 0, width, height() ), lv->tqcolorGroup(),
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->tqstyle().tqdrawComplexControl( 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* tqparent, KIRC::Engine *engine )
: TQWidget( tqparent ), m_engine( engine )
{
ChannelListLayout = new TQVBoxLayout( this, 11, 6, "ChannelListLayout");
tqlayout72_2 = new TQHBoxLayout( 0, 0, 6, "tqlayout72_2");
textLabel1_2 = new TQLabel( this, "textLabel1_2" );
tqlayout72_2->addWidget( textLabel1_2 );
channelSearch = new TQLineEdit( this, "channelSearch" );
tqlayout72_2->addWidget( channelSearch );
numUsers = new TQSpinBox( 0, 32767, 1, this, "num_users" );
numUsers->setSuffix( i18n(" members") );
tqlayout72_2->addWidget( numUsers );
mSearchButton = new TQPushButton( this, "mSearchButton" );
tqlayout72_2->addWidget( mSearchButton );
ChannelListLayout->addLayout( tqlayout72_2 );
mChannelList = new KListView( 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::tqStatus) ),
this, TQT_SLOT( slotStatusChanged(KIRC::Engine::tqStatus) ) );
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::tqStatus newtqStatus)
{
switch(newtqStatus) {
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"