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.
509 lines
11 KiB
509 lines
11 KiB
/*******************************************************************
|
|
|
|
aListBox
|
|
|
|
$$Id$$
|
|
|
|
List box that outputs a right click mouse so I can popup a qpopupmenu.
|
|
|
|
Does special sorting, and maintains a two part list, one for ops,
|
|
other for users.
|
|
|
|
nothing special.
|
|
|
|
*******************************************************************/
|
|
|
|
#include "alistbox.h"
|
|
#include "nickColourMaker.h"
|
|
|
|
#include <tqdragobject.h>
|
|
#include <tqpainter.h>
|
|
|
|
#include <kdebug.h>
|
|
#include <kglobal.h>
|
|
#include <kurldrag.h>
|
|
|
|
aListBox::aListBox(TQWidget *parent, const char *name )
|
|
: TQListBox(parent,name)
|
|
{
|
|
clear();
|
|
p_scroll = palette().copy();
|
|
setAcceptDrops( true );
|
|
connect(this, TQT_SIGNAL(selected (const TQString&)),
|
|
this, TQT_SIGNAL(selectedNick(const TQString&)));
|
|
|
|
m_nickListDirty = true;
|
|
|
|
updateNickPrefixWidth();
|
|
|
|
connect( this, TQT_SIGNAL( contextMenuRequested( TQListBoxItem *, const TQPoint & ) ),
|
|
this, TQT_SLOT( reEmitContextMenuRequest( TQListBoxItem * ) ) );
|
|
}
|
|
|
|
aListBox::~aListBox()
|
|
{
|
|
}
|
|
|
|
void aListBox::reEmitContextMenuRequest( TQListBoxItem *item )
|
|
{
|
|
emit contextMenuRequested( index( item ) );
|
|
}
|
|
|
|
void aListBox::clear()
|
|
{
|
|
TQListBox::clear();
|
|
}
|
|
|
|
|
|
void aListBox::inSort ( nickListItem *lbi)
|
|
{
|
|
int insert;
|
|
bool found;
|
|
insert = searchFor(lbi->text(), found, lbi->op());
|
|
if(found == TRUE){
|
|
//kdDebug(5008) << lbi->text() << " is already in nick list!" << endl;
|
|
return;
|
|
}
|
|
insertItem(lbi, insert);
|
|
// for(uint index = 0; index < count(); index++){
|
|
// debug("%d is %s", index, text(index));
|
|
// }
|
|
|
|
m_nickListDirty = true;
|
|
}
|
|
|
|
void aListBox::inSort ( TQString text, bool top)
|
|
{
|
|
nickListItem *nli = new nickListItem();
|
|
nli->setText(text);
|
|
if(top == TRUE)
|
|
nli->setOp(TRUE);
|
|
inSort(nli);
|
|
}
|
|
|
|
int aListBox::findSep()
|
|
{
|
|
uint i = 0;
|
|
for(; i < count(); i++)
|
|
if(item(i)->op() == FALSE)
|
|
break; // stop now
|
|
|
|
return i;
|
|
|
|
}
|
|
int aListBox::searchFor(const TQString &nick, bool &found, bool top)
|
|
{
|
|
int min = 0, max = 0;
|
|
int current = 0, compare = 0;
|
|
int real_max = 0;
|
|
int insert;
|
|
|
|
found = FALSE;
|
|
|
|
// If there's nothing in the list, don't try and search it, etc
|
|
|
|
if(count() == 0){
|
|
insert = 0;
|
|
}
|
|
else{
|
|
int sep = findSep();
|
|
if(sep >= 0){
|
|
if(top == TRUE){
|
|
min = 0;
|
|
max = (sep >= 1) ? sep - 1 : 0;
|
|
}
|
|
else{
|
|
min = sep;
|
|
max = count() - 1;
|
|
}
|
|
}
|
|
else
|
|
current = -1;
|
|
|
|
real_max = max;
|
|
current = (min + max)/2; // + (max-min)%2;
|
|
insert = current;
|
|
int last_current = -1;
|
|
uint loop = 0; // Most loops should be log_2 count(), but...
|
|
do {
|
|
if(current == last_current){
|
|
// debug("Insert looping on %s", nick.data());
|
|
// current++;
|
|
break; // we're looping, so stop
|
|
}
|
|
if(current >= max)
|
|
break; // Don't go too far
|
|
last_current = current;
|
|
|
|
compare = text(current).lower().compare(nick.lower());
|
|
if(compare < 0){
|
|
min = current;
|
|
insert = current + 1;
|
|
// debug("1 < 0: %s is greater then: %s, min: %d max: %d current: %d", nick.data(), text(current), min, max, current);
|
|
}
|
|
else if(compare > 0){
|
|
max = current;
|
|
insert = current;
|
|
// debug("1 > 0: %s is less then: %s, min: %d max: %d current: %d", nick.data(), text(current), min, max, current);
|
|
}
|
|
else {// We got a match?
|
|
insert = current;
|
|
min = current;
|
|
found = TRUE;
|
|
break;
|
|
}
|
|
current = (min + max)/2;
|
|
loop++; // Infinite loop detector increment
|
|
} while(max != min && loop < count());
|
|
|
|
if(current >= real_max - 1){
|
|
compare = text(real_max).lower().compare(nick.lower());
|
|
if(compare < 0){
|
|
min = current;
|
|
insert = real_max + 1;
|
|
// debug("End check got one!");
|
|
}
|
|
else if (compare == 0){// We got a match
|
|
insert = real_max + 1;
|
|
min = real_max;
|
|
found = TRUE;
|
|
}
|
|
}
|
|
|
|
// Sanity check
|
|
if((top == TRUE && insert > sep) ||
|
|
(top == FALSE && insert < sep)){
|
|
insert = sep;
|
|
}
|
|
|
|
if(loop == count())
|
|
{
|
|
// debug("Loop inifitly on: %s", nick.data());
|
|
}
|
|
|
|
if(found == TRUE){
|
|
// debug("Found %s", nick.data());
|
|
return min; // We found one, so return the number found
|
|
}
|
|
}
|
|
// debug("%s is at %d", nick.data(), insert);
|
|
return insert;
|
|
|
|
}
|
|
bool aListBox::isTop(int index)
|
|
{
|
|
if(index >= findSep())
|
|
return FALSE;
|
|
else
|
|
return TRUE;
|
|
}
|
|
|
|
int aListBox::findNick(const TQString &str)
|
|
{
|
|
bool found;
|
|
int index;
|
|
index = searchFor(str, found, TRUE);
|
|
if(found == TRUE)
|
|
return index;
|
|
index = searchFor(str, found, FALSE);
|
|
if(found == TRUE)
|
|
return index;
|
|
// debug("Did not find: %s", str.data());
|
|
return -1;
|
|
}
|
|
|
|
nickListItem *aListBox::item(int index){
|
|
return (nickListItem *) TQListBox::item(index);
|
|
}
|
|
|
|
void aListBox::dragMoveEvent( TQDragMoveEvent *e )
|
|
{
|
|
bool ok = (count() > 0 && KURLDrag::canDecode( e ));
|
|
|
|
if(!ok)
|
|
ok = TQTextDrag::canDecode(e);
|
|
|
|
e->accept( ok );
|
|
if ( ok )
|
|
setCurrentItem( itemAt( e->pos() ));
|
|
}
|
|
|
|
|
|
void aListBox::dropEvent( TQDropEvent *e )
|
|
{
|
|
TQListBoxItem *item = itemAt( e->pos() );
|
|
if ( !item )
|
|
return;
|
|
|
|
setCurrentItem( item );
|
|
|
|
TQStringList urls;
|
|
KURLDrag::decodeLocalFiles( e, urls );
|
|
|
|
TQString text;
|
|
|
|
if ( !urls.isEmpty() )
|
|
emit urlsDropped( urls, item->text() );
|
|
else if(TQTextDrag::decode(e, text)){
|
|
emit textDropped( item, text);
|
|
}
|
|
}
|
|
|
|
bool aListBox::needNickPrefix() const
|
|
{
|
|
if ( m_nickListDirty ) {
|
|
updateNeedNickPrefixFlag();
|
|
const_cast<aListBox *>( this )->updateNickPrefixWidth();
|
|
}
|
|
|
|
return m_needNickPrefix;
|
|
}
|
|
|
|
void aListBox::updateNeedNickPrefixFlag() const
|
|
{
|
|
m_needNickPrefix = false;
|
|
|
|
if(ksopts->useColourNickList == false){
|
|
TQListBoxItem *item = firstItem();
|
|
for (; item; item = item->next() )
|
|
{
|
|
nickListItem *nickItem = static_cast<nickListItem *>( item );
|
|
if ( nickItem->op() ||
|
|
nickItem->voice() ||
|
|
nickItem->away() ||
|
|
nickItem->ircOp() )
|
|
{
|
|
m_needNickPrefix = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
m_nickListDirty = false;
|
|
}
|
|
|
|
void aListBox::fontChange( const TQFont &f )
|
|
{
|
|
TQListBox::fontChange( f );
|
|
updateNickPrefixWidth();
|
|
}
|
|
|
|
void aListBox::updateNickPrefixWidth()
|
|
{
|
|
TQFontMetrics metrics( font() );
|
|
|
|
m_nickPrefixWidth = 0;
|
|
|
|
if(ksopts->useColourNickList == false){
|
|
nickListItem *item = static_cast<nickListItem *>( firstItem() );
|
|
for ( ; item; item = static_cast<nickListItem *>( item->next() ) )
|
|
m_nickPrefixWidth = kMax( m_nickPrefixWidth, metrics.width( item->nickPrefix() ) );
|
|
|
|
// padding
|
|
}
|
|
m_nickPrefixWidth += metrics.width( " " );
|
|
}
|
|
|
|
void aListBox::clearAdvOps()
|
|
{
|
|
nickListItem *item = static_cast<nickListItem *>( firstItem() );
|
|
for ( ; item; item = static_cast<nickListItem *>( item->next() ) ){
|
|
if(item->away() || item->ircOp()){
|
|
item->setIrcOp(false);
|
|
item->setAway(false);
|
|
updateItem(item);
|
|
}
|
|
}
|
|
triggerUpdate(false);
|
|
m_nickListDirty = true;
|
|
|
|
}
|
|
|
|
nickListItem::nickListItem()
|
|
: TQListBoxItem()
|
|
{
|
|
is_op = FALSE;
|
|
is_voice = FALSE;
|
|
is_away = FALSE;
|
|
is_ircop = FALSE;
|
|
forcedCol = 0x0;
|
|
}
|
|
|
|
nickListItem::nickListItem(const nickListItem &old)
|
|
: TQListBoxItem()
|
|
{
|
|
is_op = old.is_op;
|
|
is_voice = old.is_voice;
|
|
is_away = old.is_away;
|
|
is_ircop = old.is_ircop;
|
|
string = old.string;
|
|
forcedCol = old.forcedCol;
|
|
}
|
|
|
|
nickListItem::~nickListItem()
|
|
{
|
|
string.truncate(0);
|
|
}
|
|
|
|
void nickListItem::setOp(bool _op)
|
|
{
|
|
is_op = _op;
|
|
if ( listBox() )
|
|
static_cast<aListBox *>( listBox() )->setNickListDirty();
|
|
}
|
|
|
|
void nickListItem::setVoice(bool _voice)
|
|
{
|
|
is_voice = _voice;
|
|
if ( listBox() )
|
|
static_cast<aListBox *>( listBox() )->setNickListDirty();
|
|
}
|
|
void nickListItem::setAway(bool _away)
|
|
{
|
|
is_away = _away;
|
|
if ( listBox() )
|
|
static_cast<aListBox *>( listBox() )->setNickListDirty();
|
|
}
|
|
|
|
void nickListItem::setIrcOp(bool _ircop)
|
|
{
|
|
is_ircop = _ircop;
|
|
if ( listBox() )
|
|
static_cast<aListBox *>( listBox() )->setNickListDirty();
|
|
}
|
|
|
|
void nickListItem::forceColour(const TQColor *col)
|
|
{
|
|
forcedCol = col;
|
|
}
|
|
|
|
void nickListItem::paint(TQPainter *p)
|
|
{
|
|
TQFontMetrics fm = p->fontMetrics();
|
|
int yPos; // vertical text position
|
|
|
|
int nickPosX = 3;
|
|
yPos = fm.ascent() + fm.leading()/2;
|
|
TQPen pen = p->pen();
|
|
TQFont font = p->font();
|
|
if(ksopts->useColourNickList == true) {
|
|
if(ksopts->nickColourization){
|
|
|
|
if(!isSelected()) {
|
|
if(forcedCol && forcedCol->isValid())
|
|
p->setPen(*forcedCol);
|
|
else
|
|
p->setPen(nickColourMaker::colourMaker()->findFg(text()));
|
|
}
|
|
else {
|
|
p->setPen(ksopts->selForegroundColor);
|
|
}
|
|
|
|
if(is_voice == TRUE){
|
|
TQPen open = p->pen();
|
|
p->setPen(ksopts->channelColor);
|
|
p->drawText( nickPosX, yPos, "+" );
|
|
nickPosX += fm.width( "+" );
|
|
p->setPen(open);
|
|
// p->fillRect(0,0, listBox()->maxItemWidth(), height(listBox()), TQBrush(ksopts->channelColor, Qt::Dense7Pattern));
|
|
}
|
|
if(is_op == TRUE) {
|
|
TQPen open = p->pen();
|
|
p->setPen(ksopts->errorColor);
|
|
p->drawText( nickPosX, yPos, "@" );
|
|
nickPosX += fm.width( "@" );
|
|
p->setPen(open);
|
|
// p->fillRect(0,0, listBox()->maxItemWidth(), height(listBox()), TQBrush(ksopts->errorColor, Qt::Dense7Pattern));
|
|
}
|
|
if(is_away == TRUE)
|
|
p->setPen(p->pen().color().dark(150));
|
|
if(is_ircop == TRUE){
|
|
TQPen open = p->pen();
|
|
p->setPen(ksopts->errorColor);
|
|
p->drawText( nickPosX, yPos, "*" );
|
|
nickPosX += fm.width( "*" );
|
|
p->setPen(open);
|
|
|
|
}
|
|
|
|
}
|
|
else {
|
|
if(is_voice == TRUE)
|
|
p->setPen(ksopts->channelColor);
|
|
if(is_op == TRUE)
|
|
p->setPen(ksopts->errorColor);
|
|
if(is_away == TRUE)
|
|
p->setPen(p->pen().color().dark(150));
|
|
if(is_ircop == TRUE){
|
|
TQFont bfont = font;
|
|
bfont.setBold(TRUE);
|
|
p->setFont(bfont);
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
}
|
|
|
|
if(ksopts->useColourNickList == false) {
|
|
aListBox *lb = static_cast<aListBox *>( listBox() );
|
|
|
|
if ( lb->needNickPrefix() )
|
|
{
|
|
p->drawText( 3, yPos, nickPrefix() );
|
|
|
|
nickPosX += lb->nickPrefixWidth();
|
|
}
|
|
}
|
|
p->drawText( nickPosX, yPos, text() );
|
|
|
|
p->setPen(pen);
|
|
p->setFont(font);
|
|
}
|
|
|
|
TQString nickListItem::nickPrefix() const
|
|
{
|
|
TQString prefix;
|
|
|
|
if ( voice() )
|
|
prefix += aListBox::nickPrefixVoice();
|
|
if ( op() )
|
|
prefix += aListBox::nickPrefixOp();
|
|
if ( away() )
|
|
prefix += aListBox::nickPrefixAway();
|
|
if ( ircOp() )
|
|
prefix += aListBox::nickPrefixIrcOp();
|
|
|
|
if ( !prefix.isEmpty() )
|
|
prefix.prepend( "+" );
|
|
|
|
return prefix;
|
|
}
|
|
|
|
int nickListItem::height(const TQListBox *lb ) const
|
|
{
|
|
return lb->fontMetrics().lineSpacing() + 1;
|
|
}
|
|
|
|
int nickListItem::width(const TQListBox *lb ) const
|
|
{
|
|
return
|
|
static_cast<const aListBox *>( lb )->nickPrefixWidth() +
|
|
lb->fontMetrics().width( text() ) + 6;
|
|
}
|
|
|
|
const TQPixmap* nickListItem::pixmap() const
|
|
{
|
|
return 0l;
|
|
}
|
|
|
|
nickListItem &nickListItem::operator= (const nickListItem &nli)
|
|
{
|
|
string = nli.string;
|
|
is_op = nli.is_op;
|
|
is_voice = nli.is_voice;
|
|
is_away = nli.is_away;
|
|
is_ircop = nli.is_ircop;
|
|
return (*this);
|
|
}
|
|
#include "alistbox.moc"
|