summaryrefslogtreecommitdiffstats
path: root/ksirc/alistbox.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ksirc/alistbox.cpp')
-rw-r--r--ksirc/alistbox.cpp508
1 files changed, 508 insertions, 0 deletions
diff --git a/ksirc/alistbox.cpp b/ksirc/alistbox.cpp
new file mode 100644
index 00000000..9b632676
--- /dev/null
+++ b/ksirc/alistbox.cpp
@@ -0,0 +1,508 @@
+/*******************************************************************
+
+ 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 <qdragobject.h>
+#include <qpainter.h>
+
+#include <kdebug.h>
+#include <kglobal.h>
+#include <kurldrag.h>
+
+aListBox::aListBox(QWidget *parent, const char *name )
+ : QListBox(parent,name)
+{
+ clear();
+ p_scroll = palette().copy();
+ setAcceptDrops( true );
+ connect(this, SIGNAL(selected (const QString&)),
+ this, SIGNAL(selectedNick(const QString&)));
+
+ m_nickListDirty = true;
+
+ updateNickPrefixWidth();
+
+ connect( this, SIGNAL( contextMenuRequested( QListBoxItem *, const QPoint & ) ),
+ this, SLOT( reEmitContextMenuRequest( QListBoxItem * ) ) );
+}
+
+aListBox::~aListBox()
+{
+}
+
+void aListBox::reEmitContextMenuRequest( QListBoxItem *item )
+{
+ emit contextMenuRequested( index( item ) );
+}
+
+void aListBox::clear()
+{
+ QListBox::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 ( QString 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 QString &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 QString &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 *) QListBox::item(index);
+}
+
+void aListBox::dragMoveEvent( QDragMoveEvent *e )
+{
+ bool ok = (count() > 0 && KURLDrag::canDecode( e ));
+
+ if(!ok)
+ ok = QTextDrag::canDecode(e);
+
+ e->accept( ok );
+ if ( ok )
+ setCurrentItem( itemAt( e->pos() ));
+}
+
+
+void aListBox::dropEvent( QDropEvent *e )
+{
+ QListBoxItem *item = itemAt( e->pos() );
+ if ( !item )
+ return;
+
+ setCurrentItem( item );
+
+ QStringList urls;
+ KURLDrag::decodeLocalFiles( e, urls );
+
+ QString text;
+
+ if ( !urls.isEmpty() )
+ emit urlsDropped( urls, item->text() );
+ else if(QTextDrag::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){
+ QListBoxItem *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 QFont &f )
+{
+ QListBox::fontChange( f );
+ updateNickPrefixWidth();
+}
+
+void aListBox::updateNickPrefixWidth()
+{
+ QFontMetrics 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()
+ : QListBoxItem()
+{
+ is_op = FALSE;
+ is_voice = FALSE;
+ is_away = FALSE;
+ is_ircop = FALSE;
+ forcedCol = 0x0;
+}
+
+nickListItem::nickListItem(const nickListItem &old)
+ : QListBoxItem()
+{
+ 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 QColor *col)
+{
+ forcedCol = col;
+}
+
+void nickListItem::paint(QPainter *p)
+{
+ QFontMetrics fm = p->fontMetrics();
+ int yPos; // vertical text position
+
+ int nickPosX = 3;
+ yPos = fm.ascent() + fm.leading()/2;
+ QPen pen = p->pen();
+ QFont 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){
+ QPen 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()), QBrush(ksopts->channelColor, Qt::Dense7Pattern));
+ }
+ if(is_op == TRUE) {
+ QPen 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()), QBrush(ksopts->errorColor, Qt::Dense7Pattern));
+ }
+ if(is_away == TRUE)
+ p->setPen(p->pen().color().dark(150));
+ if(is_ircop == TRUE){
+ QPen 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){
+ QFont 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);
+}
+
+QString nickListItem::nickPrefix() const
+{
+ QString 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 QListBox *lb ) const
+{
+ return lb->fontMetrics().lineSpacing() + 1;
+}
+
+int nickListItem::width(const QListBox *lb ) const
+{
+ return
+ static_cast<const aListBox *>( lb )->nickPrefixWidth() +
+ lb->fontMetrics().width( text() ) + 6;
+}
+
+const QPixmap* 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"