#include "qcompletionedit.h"
#include <tqlistbox.h>
#include <tqsizegrip.h>
#include <tqapplication.h>
#include <tqvbox.h>

QCompletionEdit::QCompletionEdit( TQWidget *parent, const char *name )
    : TQLineEdit( parent, name ), aAdd( false ), caseSensitive( false )
{
    popup = new TQVBox( 0, 0, WType_Popup );
    popup->setFrameStyle( TQFrame::Box | TQFrame::Plain );
    popup->setLineWidth( 1 );
    popup->hide();

    listbox = new TQListBox( popup );
    listbox->setFrameStyle( TQFrame::NoFrame );
    listbox->setLineWidth( 1 );
    listbox->installEventFilter( this );
    listbox->setHScrollBarMode( TQScrollView::AlwaysOn );
    listbox->setVScrollBarMode( TQScrollView::AlwaysOn );
    listbox->setCornerWidget( new TQSizeGrip( listbox, "completion sizegrip" ) );
    connect( this, TQT_SIGNAL( textChanged( const TQString & ) ),
	     this, TQT_SLOT( textDidChange( const TQString & ) ) );
    popup->setFocusProxy( listbox );
    installEventFilter( this );
}

bool QCompletionEdit::autoAdd() const
{
    return aAdd;
}

TQStringList QCompletionEdit::completionList() const
{
    return compList;
}

void QCompletionEdit::setCompletionList( const TQStringList &l )
{
    compList = l;
}

void QCompletionEdit::setAutoAdd( bool add )
{
    aAdd = add;
}

void QCompletionEdit::textDidChange( const TQString &text )
{
    if ( text.isEmpty() ) {
	popup->close();
	return;
    }
    updateListBox();
    placeListBox();
}

void QCompletionEdit::placeListBox()
{
    if ( listbox->count() == 0 ) {
	popup->close();
	return;
    }

    popup->resize( TQMAX( listbox->sizeHint().width() + listbox->verticalScrollBar()->width() + 4, width() ),
		   listbox->sizeHint().height() + listbox->horizontalScrollBar()->height() + 4 );

    TQPoint p( mapToGlobal( TQPoint( 0, 0 ) ) );
    if ( p.y() + height() + popup->height() <= TQApplication::desktop()->height() )
	popup->move( p.x(), p.y() + height() );
    else
	popup->move( p.x(), p.y() - listbox->height() );
    popup->show();
    listbox->setCurrentItem( 0 );
    listbox->setSelected( 0, true );
    setFocus();
}

void QCompletionEdit::updateListBox()
{
    listbox->clear();
    if ( compList.isEmpty() )
	return;
    for ( TQStringList::Iterator it = compList.begin(); it != compList.end(); ++it ) {
	if ( caseSensitive && (*it).left( text().length() ) == text() ||
	     !caseSensitive && (*it).left( text().length() ).lower() == text().lower() )
	    listbox->insertItem( *it );
    }
}

bool QCompletionEdit::eventFilter( TQObject *o, TQEvent *e )
{
    if ( TQT_BASE_OBJECT(o) == TQT_BASE_OBJECT(popup) || TQT_BASE_OBJECT(o) == TQT_BASE_OBJECT(listbox) || TQT_BASE_OBJECT(o) == TQT_BASE_OBJECT(listbox->viewport()) ) {
	if ( e->type() == TQEvent::KeyPress ) {
	    TQKeyEvent *ke = (TQKeyEvent*)e;
	    if ( ke->key() == Key_Enter || ke->key() == Key_Return || ke->key() == Key_Tab ) {
		if ( ke->key() == Key_Tab && listbox->count() > 1 &&
		     listbox->currentItem() < (int)listbox->count() - 1 ) {
		    listbox->setCurrentItem( listbox->currentItem() + 1 );
		    return true;
		}
		popup->close();
		setFocus();
		blockSignals( true );
		setText( listbox->currentText() );
		blockSignals( false );
		emit chosen( text() );
		return true;
	    } else if ( ke->key() == Key_Left || ke->key() == Key_Right ||
			ke->key() == Key_Up || ke->key() == Key_Down ||
			ke->key() == Key_Home || ke->key() == Key_End ||
			ke->key() == Key_Prior || ke->key() == Key_Next ) {
		return false;
	    } else if ( ke->key() == Key_Escape ) {
		popup->close();
		setFocus();
	    } else if ( ke->key() != Key_Shift && ke->key() != Key_Control &&
			ke->key() != Key_Alt ) {
		updateListBox();
		if ( listbox->count() == 0 || text().length() == 0 ) {
		    popup->close();
		    setFocus();
		}
		TQApplication::sendEvent( this, e );
		return true;
	    }
	} else if ( e->type() == TQEvent::MouseButtonDblClick ) {
	    popup->close();
	    setFocus();
	    blockSignals( true );
	    setText( listbox->currentText() );
	    blockSignals( false );
	    emit chosen( text() );
	    return true;
	}
    } else if ( TQT_BASE_OBJECT(o) == TQT_BASE_OBJECT(this) ) {
	if ( e->type() == TQEvent::KeyPress ) {
	    TQKeyEvent *ke = (TQKeyEvent*)e;
	    if ( ke->key() == Key_Up ||
		 ke->key() == Key_Down ||
		 ke->key() == Key_Prior ||
		 ke->key() == Key_Next ||
		 ke->key() == Key_Return ||
		 ke->key() == Key_Enter ||
		 ke->key() == Key_Tab ||
		 ke->key() ==  Key_Escape ) {
		TQApplication::sendEvent( listbox, e );
		return true;
	    }
	}
    }
    return TQLineEdit::eventFilter( o, e );
}

void QCompletionEdit::addCompletionEntry( const TQString &entry )
{
    if ( compList.find( entry ) == compList.end() ) {
	compList << entry;
	compList.sort();
    }
}

void QCompletionEdit::removeCompletionEntry( const TQString &entry )
{
    TQStringList::Iterator it = compList.find( entry );
    if ( it != compList.end() )
	compList.remove( it );
}

void QCompletionEdit::setCaseSensitive( bool b )
{
    caseSensitive = b;
}

bool QCompletionEdit::isCaseSensitive() const
{
    return caseSensitive;
}

void QCompletionEdit::clear()
{
    TQLineEdit::clear();
    compList.clear();
}
#include "qcompletionedit.moc"
