//=============================================================================
//
//   File : kvi_tal_listview.cpp
//   Creation date : Mon Jan 22 2007 11:25:08 by Szymon Stefanek
//
//   This file is part of the KVirc irc client distribution
//   Copyright (C) 2007 Szymon Stefanek (pragma at kvirc dot net)
//
//   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 opinion) any later version.
//
//   This program is distributed in the HOPE that it will be USEFUL,
//   but WITHOUT ANY WARRANTY; without even the implied warranty of
//   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
//   See the GNU General Public License for more details.
//
//   You should have received a copy of the GNU General Public License
//   along with this program. If not, write to the Free Software Foundation,
//   Inc. ,51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
//=============================================================================

#define __KVILIB__
#include "kvi_tal_listview.h"

#include "kvi_pointerhashtable.h"


	#include <tqpainter.h>
	#include <tqstyle.h>
	#include <tqheader.h>
	#include <tqapplication.h>

	KviTalListView::KviTalListView(TQWidget * pParent)
	: TQListView(pParent)
	{
		connect(this,TQ_SIGNAL(selectionChanged(TQListViewItem *)),this,TQ_SLOT(redirect_selectionChanged(TQListViewItem *)));
		connect(this,TQ_SIGNAL(currentChanged(TQListViewItem *)),this,TQ_SLOT(redirect_currentChanged(TQListViewItem *)));
		connect(this,TQ_SIGNAL(clicked(TQListViewItem *)),this,TQ_SLOT(redirect_clicked(TQListViewItem *)));
		connect(this,TQ_SIGNAL(clicked(TQListViewItem *,const TQPoint &,int)),this,TQ_SLOT(redirect_clicked(TQListViewItem *,const TQPoint &,int)));
		connect(this,TQ_SIGNAL(pressed(TQListViewItem *)),this,TQ_SLOT(redirect_pressed(TQListViewItem *)));
		connect(this,TQ_SIGNAL(pressed(TQListViewItem *,const TQPoint &,int)),this,TQ_SLOT(redirect_pressed(TQListViewItem *,const TQPoint &,int)));
		connect(this,TQ_SIGNAL(doubleClicked(TQListViewItem *)),this,TQ_SLOT(redirect_doubleClicked(TQListViewItem *)));
		connect(this,TQ_SIGNAL(doubleClicked(TQListViewItem *,const TQPoint &,int)),this,TQ_SLOT(redirect_doubleClicked(TQListViewItem *,const TQPoint &,int)));
		connect(this,TQ_SIGNAL(returnPressed(TQListViewItem *)),this,TQ_SLOT(redirect_returnPressed(TQListViewItem *)));
		connect(this,TQ_SIGNAL(spacePressed(TQListViewItem *)),this,TQ_SLOT(redirect_spacePressed(TQListViewItem *)));
		connect(this,TQ_SIGNAL(rightButtonClicked(TQListViewItem *,const TQPoint &,int)),this,TQ_SLOT(redirect_rightButtonClicked(TQListViewItem *,const TQPoint &,int)));
		connect(this,TQ_SIGNAL(rightButtonPressed(TQListViewItem *,const TQPoint &,int)),this,TQ_SLOT(redirect_rightButtonPressed(TQListViewItem *,const TQPoint &,int)));
		connect(this,TQ_SIGNAL(mouseButtonClicked(int,TQListViewItem *,const TQPoint &,int)),this,TQ_SLOT(redirect_mouseButtonClicked(int,TQListViewItem *,const TQPoint &,int)));
		connect(this,TQ_SIGNAL(mouseButtonPressed(int,TQListViewItem *,const TQPoint &,int)),this,TQ_SLOT(redirect_mouseButtonPressed(int,TQListViewItem *,const TQPoint &,int)));
		connect(this,TQ_SIGNAL(contextMenuRequested(TQListViewItem *,const TQPoint &,int)),this,TQ_SLOT(redirect_contextMenuRequested(TQListViewItem *,const TQPoint &,int)));
		connect(this,TQ_SIGNAL(onItem(TQListViewItem *)),this,TQ_SLOT(redirect_onItem(TQListViewItem *)));
		connect(this,TQ_SIGNAL(expanded(TQListViewItem *)),this,TQ_SLOT(redirect_expanded(TQListViewItem *)));
		connect(this,TQ_SIGNAL(collapsed(TQListViewItem *)),this,TQ_SLOT(redirect_collapsed(TQListViewItem *)));
	}

	void KviTalListView::redirect_selectionChanged(TQListViewItem * pItem)
	{
		emit selectionChanged((KviTalListViewItem *)pItem);
	}

	void KviTalListView::redirect_currentChanged(TQListViewItem * pItem)
	{
		emit currentChanged((KviTalListViewItem *)pItem);
	}

	void KviTalListView::redirect_clicked(TQListViewItem * pItem)
	{
		emit clicked((KviTalListViewItem *)pItem);
	}

	void KviTalListView::redirect_clicked(TQListViewItem * pItem,const TQPoint &pnt,int uColumn)
	{
		emit clicked((KviTalListViewItem *)pItem,pnt,uColumn);
	}

	void KviTalListView::redirect_pressed(TQListViewItem * pItem)
	{
		emit pressed((KviTalListViewItem *)pItem);
	}

	void KviTalListView::redirect_pressed(TQListViewItem * pItem,const TQPoint &pnt,int uColumn)
	{
		emit pressed((KviTalListViewItem *)pItem,pnt,uColumn);
	}

	void KviTalListView::redirect_doubleClicked(TQListViewItem * pItem)
	{
		emit doubleClicked((KviTalListViewItem *)pItem);
	}

	void KviTalListView::redirect_doubleClicked(TQListViewItem * pItem,const TQPoint &pnt,int uColumn)
	{
		emit doubleClicked((KviTalListViewItem *)pItem,pnt,uColumn);
	}

	void KviTalListView::redirect_returnPressed(TQListViewItem * pItem)
	{
		emit returnPressed((KviTalListViewItem *)pItem);
	}

	void KviTalListView::redirect_spacePressed(TQListViewItem * pItem)
	{
		emit spacePressed((KviTalListViewItem *)pItem);
	}

	void KviTalListView::redirect_rightButtonClicked(TQListViewItem * pItem,const TQPoint &pnt,int uColumn)
	{
		emit rightButtonClicked((KviTalListViewItem *)pItem,pnt,uColumn);
	}

	void KviTalListView::redirect_rightButtonPressed(TQListViewItem * pItem,const TQPoint &pnt,int uColumn)
	{
		emit rightButtonPressed((KviTalListViewItem *)pItem,pnt,uColumn);
	}

	void KviTalListView::redirect_mouseButtonClicked(int iButton,TQListViewItem * pItem,const TQPoint &pnt,int uColumn)
	{
		emit mouseButtonClicked(iButton,(KviTalListViewItem *)pItem,pnt,uColumn);
	}

	void KviTalListView::redirect_mouseButtonPressed(int iButton,TQListViewItem * pItem,const TQPoint &pnt,int uColumn)
	{
		emit mouseButtonPressed(iButton,(KviTalListViewItem *)pItem,pnt,uColumn);
	}

	void KviTalListView::redirect_contextMenuRequested(TQListViewItem * pItem,const TQPoint &pnt,int uColumn)
	{
		emit contextMenuRequested((KviTalListViewItem *)pItem,pnt,uColumn);
	}

	void KviTalListView::redirect_onItem(TQListViewItem * pItem)
	{
		emit onItem((KviTalListViewItem *)pItem);
	}

	void KviTalListView::redirect_expanded(TQListViewItem * pItem)
	{
		emit expanded((KviTalListViewItem *)pItem);
	}

	void KviTalListView::redirect_collapsed(TQListViewItem * pItem)
	{
		emit collapsed((KviTalListViewItem *)pItem);
	}

	struct KviTalCheckListItemPrivate
	{
	    KviTalCheckListItemPrivate():
		exclusive( 0 ),
		currentState( KviTalCheckListItem::Off ),
		statesDict( 0 ),
		tristate( FALSE ) {}
	
	    KviTalCheckListItem *exclusive;
	    KviTalCheckListItem::ToggleState currentState;
	    KviPointerHashTable<void *,KviTalCheckListItem::ToggleState> *statesDict;
	    bool tristate;
	};
	
	// ### obscenity is warranted.
	
	KviTalCheckListItem::KviTalCheckListItem( KviTalCheckListItem *parent, const TQString &text,
					Type tt )
	    : KviTalListViewItem( parent, text, TQString() )
	{
	    myType = tt;
	    init();
	    if ( myType == RadioButton ) {
		if ( parent->type() != RadioButtonController )
		    tqWarning( "KviTalCheckListItem::KviTalCheckListItem(), radio button must be "
			      "child of a controller" );
		else
		    d->exclusive = parent;
	    }
	}
	
	KviTalCheckListItem::KviTalCheckListItem( KviTalCheckListItem *parent, KviTalListViewItem *after,
	 				const TQString &text, Type tt )
	    : KviTalListViewItem( parent, after, text )
	{
	    myType = tt;
	    init();
	    if ( myType == RadioButton ) {
	 	if ( parent->type() != RadioButtonController )
	 	    tqWarning( "KviTalCheckListItem::KviTalCheckListItem(), radio button must be "
			      "child of a controller" );
	 	else
	 	    d->exclusive = parent;
	    }
	}
	
	KviTalCheckListItem::KviTalCheckListItem( KviTalListViewItem *parent, const TQString &text,
					Type tt )
	    : KviTalListViewItem( parent, text, TQString() )
	{
	    myType = tt;
	    if ( myType == RadioButton ) {
	      tqWarning( "KviTalCheckListItem::KviTalCheckListItem(), radio button must be "
		       "child of a KviTalCheckListItem" );
	    }
	    init();
	}
	
	KviTalCheckListItem::KviTalCheckListItem( KviTalListViewItem *parent, KviTalListViewItem *after,
	 				const TQString &text, Type tt )
	    : KviTalListViewItem( parent, after, text )
	{
	    myType = tt;
	    if ( myType == RadioButton ) {
	 	tqWarning( "KviTalCheckListItem::KviTalCheckListItem(), radio button must be "
	 		  "child of a KviTalCheckListItem" );
	    }
	    init();
	}
	
	KviTalCheckListItem::KviTalCheckListItem( KviTalListView *parent, const TQString &text,
					Type tt )
	    : KviTalListViewItem( parent, text )
	{
	    myType = tt;
	    if ( tt == RadioButton )
		tqWarning( "KviTalCheckListItem::KviTalCheckListItem(), radio button must be "
			 "child of a KviTalCheckListItem" );
	    init();
	}
	
	KviTalCheckListItem::KviTalCheckListItem( KviTalListView *parent, KviTalListViewItem *after,
	 				const TQString &text, Type tt )
	    : KviTalListViewItem( parent, after, text )
	{
	    myType = tt;
	    if ( tt == RadioButton )
	 	tqWarning( "KviTalCheckListItem::KviTalCheckListItem(), radio button must be "
	 		  "child of a KviTalCheckListItem" );
	    init();
	}
	
	
	int KviTalCheckListItem::RTTI = 1;
	
	int KviTalCheckListItem::rtti() const
	{
	    return RTTI;
	}
	
	KviTalCheckListItem::KviTalCheckListItem( KviTalListView *parent, const TQString &text,
					const TQPixmap & p )
	    : KviTalListViewItem( parent, text )
	{
	    myType = RadioButtonController;
	    setPixmap( 0, p );
	    init();
	}
	
	KviTalCheckListItem::KviTalCheckListItem( KviTalListViewItem *parent, const TQString &text,
					const TQPixmap & p )
	    : KviTalListViewItem( parent, text )
	{
	    myType = RadioButtonController;
	    setPixmap( 0, p );
	    init();
	}
	
	void KviTalCheckListItem::init()
	{
	    d = new KviTalCheckListItemPrivate();
	    on = FALSE; // ### remove on ver 4
	    if ( myType == CheckBoxController || myType == CheckBox ) {
		d->statesDict = new KviPointerHashTable<void *,ToggleState>(101);
		d->statesDict->setAutoDelete( TRUE );
	    }
	    // CheckBoxControllers by default have tristate set to TRUE
	    if ( myType == CheckBoxController )
		setTristate( TRUE );
	}
	
	KviTalCheckListItem::~KviTalCheckListItem()
	{
	    if ( myType == RadioButton
		 && d->exclusive && d->exclusive->d
		 && d->exclusive->d->exclusive == this )
		d->exclusive->turnOffChild();
	    d->exclusive = 0; // so the children won't try to access us.
	    if ( d->statesDict )
		delete d->statesDict;
	    delete d;
	    d = 0;
	}
	
	void KviTalCheckListItem::setTristate( bool b )
	{
	    if ( ( myType != CheckBoxController ) && ( myType != CheckBox ) ) {
		tqWarning( "KviTalCheckListItem::setTristate(), has no effect on RadioButton "
			  "or RadioButtonController." );
	    	return;
	    }
	    d->tristate = b;
	}
	
	bool KviTalCheckListItem::isTristate() const
	{
	    return d->tristate;
	}
	
	KviTalCheckListItem::ToggleState KviTalCheckListItem::state() const
	{
	    if ( !isTristate() && internalState() == NoChange )
		return Off;
	    else
		return d->currentState;
	}
	
	KviTalCheckListItem::ToggleState KviTalCheckListItem::internalState() const
	{
	    return d->currentState;
	}
	
	void KviTalCheckListItem::setState( ToggleState s )
	{
	    if ( myType == CheckBoxController && state() == NoChange )
		updateStoredState( (void*) this );
	    setState( s, TRUE, TRUE );
	}
	
	void KviTalCheckListItem::setState( ToggleState s, bool update, bool store)
	{
	
	    if ( s == internalState() )
		return;
	
	    if ( myType == CheckBox ) {
		setCurrentState( s );
		stateChange( state() );
	  	if ( update && parent() && parent()->rtti() == 1
	  	     && ((KviTalCheckListItem*)parent())->type() == CheckBoxController )
	  	    ((KviTalCheckListItem*)parent())->updateController( update, store );
	    } else if ( myType == CheckBoxController ) {
		if ( s == NoChange && childCount()) {
		    restoreState( (void*) this );
		} else {
		    KviTalListViewItem *item = firstChild();
		    int childCount = 0;
		    while( item ) {
			if ( item->rtti() == 1 &&
			     ( ((KviTalCheckListItem*)item)->type() == CheckBox ||
			       ((KviTalCheckListItem*)item)->type() == CheckBoxController ) ) {
			    KviTalCheckListItem *checkItem = (KviTalCheckListItem*)item;
			    checkItem->setState( s, FALSE, FALSE );
			    childCount++;
			}
			item = item->nextSibling();
		    }
		    if ( update ) {
			if ( childCount > 0 ) {
			    ToggleState oldState = internalState();
			    updateController( FALSE, FALSE );
			    if ( oldState != internalState() &&
				 parent() && parent()->rtti() == 1 &&
				 ((KviTalCheckListItem*)parent())->type() == CheckBoxController )
				((KviTalCheckListItem*)parent())->updateController( update, store );
	
				updateController( update, store );
			} else {
			    // if there are no children we simply set the CheckBoxController and update its parent
			    setCurrentState( s );
			    stateChange( state() );
			    if ( parent() && parent()->rtti() == 1
				 && ((KviTalCheckListItem*)parent())->type() == CheckBoxController )
				((KviTalCheckListItem*)parent())->updateController( update, store );
			}
		    } else {
			setCurrentState( s );
			stateChange( state() );
		    }
	
		}
	    } else if ( myType == RadioButton ) {
		if ( s == On ) {
		    if ( d->exclusive && d->exclusive->d->exclusive != this )
			d->exclusive->turnOffChild();
		    setCurrentState( s );
		    if ( d->exclusive )
			d->exclusive->d->exclusive = this;
		} else {
		    if ( d->exclusive && d->exclusive->d->exclusive == this )
			d->exclusive->d->exclusive = 0;
		    setCurrentState( Off );
		}
		stateChange( state() );
	    }
	    repaint();
	}
	
	void KviTalCheckListItem::setCurrentState( ToggleState s )
	{
	    ToggleState old = d->currentState;
	    d->currentState = s;
	    if (d->currentState == On)
		on = TRUE;
	    else
		on = FALSE;
	
	#if defined(TQT_ACCESSIBILITY_SUPPORT)
	    if ( old != d->currentState && listView() )
		TQAccessible::updateAccessibility( listView()->viewport(), indexOfItem( this ), TQAccessible::StateChanged );
	#else
	    Q_UNUSED( old );
	#endif
	}
	
	void KviTalCheckListItem::setStoredState( ToggleState newState, void *key )
	{
	    if ( myType == CheckBox || myType == CheckBoxController )
		d->statesDict->replace( key, new ToggleState(newState) );
	}
	
	KviTalCheckListItem::ToggleState KviTalCheckListItem::storedState( void *key ) const
	{
	    if ( !d->statesDict )
		return Off;
	
	    ToggleState *foundState = d->statesDict->find( key );
	    if ( foundState )
		return ToggleState( *foundState );
	    else
		return Off;
	}
	
	void KviTalCheckListItem::turnOffChild()
	{
	    if ( myType == RadioButtonController && d->exclusive )
		d->exclusive->setOn( FALSE );
	}
	
	void KviTalCheckListItem::activate()
	{
	    KviTalListView * lv = listView();
	
	    if ( lv && !lv->isEnabled() || !isEnabled() )
		return;
	
	    TQPoint pos;
	    int boxsize = lv->style().pixelMetric(TQStyle::PM_CheckListButtonSize, lv);
	    if ( activatedPos( pos ) ) {
		bool parentControl = FALSE;
		if ( parent() && parent()->rtti() == 1  &&
		    ((KviTalCheckListItem*) parent())->type() == RadioButtonController )
		    parentControl = TRUE;
	
		int x = parentControl ? 0 : 3;
		int align = lv->columnAlignment( 0 );
		int marg = lv->itemMargin();
		int y = 0;
	
		if ( align & AlignVCenter )
		    y = ( ( height() - boxsize ) / 2 ) + marg;
		else
		    y = (lv->fontMetrics().height() + 2 + marg - boxsize) / 2;
	
		TQRect r( x, y, boxsize-3, boxsize-3 );
		// columns might have been swapped
		r.moveBy( lv->header()->sectionPos( 0 ), 0 );
		if ( !r.contains( pos ) )
		    return;
	    }
	    if ( ( myType == CheckBox ) || ( myType == CheckBoxController) )  {
		switch ( internalState() ) {
		case On:
		    setState( Off );
		    break;
		case Off:
		    if ( !isTristate() && myType == CheckBox ) {
			setState( On );
		    } else {
			setState( NoChange );
			if ( myType == CheckBoxController && internalState() != NoChange )
			    setState( On );
		    }
		    break;
		case NoChange:
		    setState( On );
		    break;
		}
		ignoreDoubleClick();
	    } else if ( myType == RadioButton ) {
		setOn( TRUE );
		ignoreDoubleClick();
	    }
	}
	
	void KviTalCheckListItem::setOn( bool b  )
	{
	    if ( b )
		setState( On , TRUE, TRUE );
	    else
		setState( Off , TRUE, TRUE );
	}
	
	void KviTalCheckListItem::stateChange( bool )
	{
	}
	
	void KviTalCheckListItem::stateChange( ToggleState s )
	{
	    stateChange( s == On );
	}
	
	void KviTalCheckListItem::restoreState( void *key, int depth )
	{
	    switch ( type() ) {
	    case CheckBox:
		setCurrentState( storedState( key ) );
		stateChange( state() );
		repaint();
		break;
	    case CheckBoxController: {
		KviTalListViewItem *item = firstChild();
		int childCount = 0;
		while ( item ) {
		    // recursively calling restoreState for children of type CheckBox and CheckBoxController
		    if ( item->rtti() == 1 &&
			 ( ((KviTalCheckListItem*)item)->type() == CheckBox ||
			   ((KviTalCheckListItem*)item)->type() == CheckBoxController ) ) {
			((KviTalCheckListItem*)item)->restoreState( key , depth+1 );
			childCount++;
		    }
		    item = item->nextSibling();
		}
		if ( childCount > 0 ) {
		    if ( depth == 0 )
			updateController( TRUE );
		    else
			updateController( FALSE );
		} else {
		    // if there are no children we retrieve the CheckBoxController state directly.
		    setState( storedState( key ), TRUE, FALSE );
		}
	    }
		break;
	    default:
		break;
	    }
	}
	
	void KviTalCheckListItem::updateController( bool update , bool store )
	{
	    if ( myType != CheckBoxController )
		return;
	
	    KviTalCheckListItem *controller = 0;
	    // checks if this CheckBoxController has another CheckBoxController as parent
	    if ( parent() && parent()->rtti() == 1
		 && ((KviTalCheckListItem*)parent())->type() == CheckBoxController )
		controller = (KviTalCheckListItem*)parent();
	
	    ToggleState theState = Off;
	    bool first = TRUE;
	    KviTalListViewItem *item = firstChild();
	    while( item && theState != NoChange ) {
		if ( item->rtti() == 1 &&
		     ( ((KviTalCheckListItem*)item)->type() == CheckBox ||
		       ((KviTalCheckListItem*)item)->type() == CheckBoxController ) ) {
		    KviTalCheckListItem *checkItem = (KviTalCheckListItem*)item;
		    if ( first ) {
			theState = checkItem->internalState();
			first = FALSE;
		    } else {
			if ( checkItem->internalState() == NoChange ||
			     theState != checkItem->internalState() )
			    theState = NoChange;
			else
			    theState = checkItem->internalState();
		    }
		}
		item = item->nextSibling();
	    }
	    if ( internalState() != theState ) {
		setCurrentState( theState );
		if ( store && ( internalState() == On || internalState() == Off ) )
		    updateStoredState( (void*) this );
		stateChange( state() );
		if ( update && controller ) {
		    controller->updateController( update, store );
		}
		repaint();
	    }
	}
	
	void KviTalCheckListItem::updateStoredState( void *key )
	{
	    if ( myType != CheckBoxController )
		return;
	
	    KviTalListViewItem *item = firstChild();
	    while( item ) {
		if ( item->rtti() == 1 ) {
		    KviTalCheckListItem *checkItem = (KviTalCheckListItem*)item;
		    if ( checkItem->type() == CheckBox )
			checkItem->setStoredState( checkItem->internalState(), key );
		    else if (checkItem->type() == CheckBoxController )
			checkItem->updateStoredState( key );
		}
		item = item->nextSibling();
	    }
	    // this state is only needed if the CheckBoxController has no CheckBox / CheckBoxController children.
	    setStoredState( internalState() , key );
	}
	
	void KviTalCheckListItem::setup()
	{
	    KviTalListViewItem::setup();
	    int h = height();
	    KviTalListView *lv = listView();
	    if ( lv )
		h = TQMAX( lv->style().pixelMetric(TQStyle::PM_CheckListButtonSize, lv),
			  h );
	    h = TQMAX( h, TQApplication::globalStrut().height() );
	    setHeight( h );
	}
	
	int KviTalCheckListItem::width( const TQFontMetrics& fm, const KviTalListView* lv, int column) const
	{
	    int r = KviTalListViewItem::width( fm, lv, column );
	    if ( column == 0 ) {
		r += lv->itemMargin();
		if ( myType == RadioButtonController && pixmap( 0 ) ) {
		    //	     r += 0;
		} else {
		    r +=  lv->style().pixelMetric(TQStyle::PM_CheckListButtonSize, lv) + 4;
		}
	    }
	    return TQMAX( r, TQApplication::globalStrut().width() );
	}
	
	void KviTalCheckListItem::paintCell( TQPainter * p, const TQColorGroup & cg,
				       int column, int width, int align )
	{
	    if ( !p )
		return;
	
	    KviTalListView *lv = listView();
	    if ( !lv )
		return;
	
	    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
		lv->paintEmptyArea( p, TQRect( 0, 0, width, height() ) );
	
	    if ( column != 0 ) {
		// The rest is text, or for subclasses to change.
		KviTalListViewItem::paintCell( p, cg, column, width, align );
		return;
	    }
	
	    bool parentControl = FALSE;
	    if ( parent() && parent()->rtti() == 1  &&
		 ((KviTalCheckListItem*) parent())->type() == RadioButtonController )
		parentControl = TRUE;
	
	    TQFontMetrics fm( lv->fontMetrics() );
	    int boxsize = lv->style().pixelMetric( myType == RadioButtonController ? TQStyle::PM_CheckListControllerSize :
						   TQStyle::PM_CheckListButtonSize, lv);
	    int marg = lv->itemMargin();
	    int r = marg;
	
	    // Draw controller / checkbox / radiobutton ---------------------
	    int styleflags = TQStyle::Style_Default;
	    if ( internalState() == On ) {
		styleflags |= TQStyle::Style_On;
	    } else if ( internalState() == NoChange ) {
		if ( myType == CheckBoxController && !isTristate() )
		    styleflags |= TQStyle::Style_Off;
		else
		    styleflags |= TQStyle::Style_NoChange;
	    } else {
		styleflags |= TQStyle::Style_Off;
	    }
	    if ( isSelected() )
		styleflags |= TQStyle::Style_Selected;
	    if ( isEnabled() && lv->isEnabled() )
		styleflags |= TQStyle::Style_Enabled;
	
	    if ( myType == RadioButtonController ) {
		int x = 0;
		if(!parentControl)
		    x += 3;
		if ( !pixmap( 0 ) ) {
		    lv->style().drawPrimitive(TQStyle::PE_CheckListController, p,
					  TQRect(x, 0, boxsize,
						fm.height() + 2 + marg),
					  cg, styleflags, TQStyleOption(this));
		    r += boxsize + 4;
		}
	    } else {
		Q_ASSERT( lv ); //###
		int x = 0;
		int y = 0;
		if ( !parentControl )
		    x += 3;
		if ( align & AlignVCenter )
		    y = ( ( height() - boxsize ) / 2 ) + marg;
		else
		    y = (fm.height() + 2 + marg - boxsize) / 2;
	
		if ( ( myType == CheckBox ) || ( myType == CheckBoxController ) ) {
		    lv->style().drawPrimitive(TQStyle::PE_CheckListIndicator, p,
					      TQRect(x, y, boxsize,
						    fm.height() + 2 + marg),
					      cg, styleflags, TQStyleOption(this));
		} else { //radio button look
		    lv->style().drawPrimitive(TQStyle::PE_CheckListExclusiveIndicator,
						      p, TQRect(x, y, boxsize,
							       fm.height() + 2 + marg),
						      cg, styleflags, TQStyleOption(this));
		}
		r += boxsize + 4;
	    }
	
	    // Draw text ----------------------------------------------------
	    p->translate( r, 0 );
	    p->setPen( TQPen( cg.text() ) );
	    KviTalListViewItem::paintCell( p, cg, column, width - r, align );
	}
	
	void KviTalCheckListItem::paintFocus( TQPainter *p, const TQColorGroup & cg,const TQRect & r )
	{
	    bool intersect = TRUE;
	    KviTalListView *lv = listView();
	    if ( lv && lv->header()->mapToActual( 0 ) != 0 ) {
		int xdepth = lv->treeStepSize() * ( depth() + ( lv->rootIsDecorated() ? 1 : 0) ) + lv->itemMargin();
		int p = lv->header()->cellPos( lv->header()->mapToActual( 0 ) );
		xdepth += p;
		intersect = r.intersects( TQRect( p, r.y(), xdepth - p + 1, r.height() ) );
	    }
	    bool parentControl = FALSE;
	    if ( parent() && parent()->rtti() == 1  &&
		 ((KviTalCheckListItem*) parent())->type() == RadioButtonController )
		parentControl = TRUE;
	    if ( myType != RadioButtonController && intersect &&
		 (lv->rootIsDecorated() || myType == RadioButton ||
		  (myType == CheckBox && parentControl) ) ) {
		TQRect rect;
		int boxsize = lv->style().pixelMetric(TQStyle::PM_CheckListButtonSize, lv);
		if ( lv->columnAlignment(0) == AlignCenter ) {
		    TQFontMetrics fm( lv->font() );
		    int bx = (lv->columnWidth(0) - (boxsize + fm.width(text())))/2 + boxsize;
		    if ( bx < 0 ) bx = 0;
		    rect.setRect( r.x() + bx + 5, r.y(), r.width() - bx - 5,
				  r.height() );
		} else
		    rect.setRect( r.x() + boxsize + 5, r.y(), r.width() - boxsize - 5,
				  r.height() );
		KviTalListViewItem::paintFocus(p, cg, rect);
	    } else {
		KviTalListViewItem::paintFocus(p, cg, r);
	    }
	}

	#include "kvi_tal_listview_qt3.moc"



