/*
 * portlistview.cc
 *
 * Copyright (c) 2002, 2003 Frerich Raabe <raabe@kde.org>
 *
 * 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. For licensing and distribution details, check the
 * accompanying file 'COPYING'.
 */
#include "history.h"
#include "portlistview.h"
#include "portmgr.h"

#include <kapplication.h>
#include <kcursor.h>
#include <kiconloader.h>
#include <klocale.h>
#include <kmainwindow.h>
#include <kstatusbar.h>

#include <qtimer.h>

namespace Barry
{
	class PortSelectCommand : public Command
	{
		public:
			PortSelectCommand();

			virtual QString text() const;
			void setup( PortListView *parent, QListViewItem *oldItem,
			            QListViewItem *newItem );

		private:
			void selectItem( QListViewItem *item );

			virtual void doExec();
			virtual void doUnexec();

			PortListView *m_parent;
			QListViewItem *m_oldItem;
			QListViewItem *m_newItem;
	};
};

using namespace Barry;

CategoryItem::CategoryItem( PortListView *parent, const QString &name ):
	KListViewItem( parent ),
	m_name( name )
{
	QString title = m_name;
	title[ 0 ] = title[ 0 ].upper();
	setText( 0, title );

	setOpen( false );
	setExpandable( true );
}

void CategoryItem::setOpen( bool open )
{
	if ( open && childCount() == 0 )
		populate();
	
	if ( open && childCount() > 0 )
		setPixmap( 0, SmallIcon( QString::fromLatin1( "folder_blue_open" ) ) );
	else
		setPixmap( 0, SmallIcon( QString::fromLatin1( "folder_blue" ) ) );

	KListViewItem::setOpen( open );

}

void CategoryItem::populate()
{
	if ( childCount() > 0 )
		return;

	listView()->setUpdatesEnabled( false );

	PortListView *parent = static_cast<PortListView *>( listView() );

	const PortList ports = PortMgr::self().ports( m_name );
	PortList::ConstIterator it = ports.begin();
	PortList::ConstIterator end = ports.end();
	for ( ; it != end; ++it ) {
		PortItem *item = new PortItem( this, *it );
		parent->m_nameDict.insert( ( *it ).name(), item );
		parent->m_portMap.insert( *it, item );
		emit parent->portNameRegistered( ( *it ).name() );
	}

	if( !ports.isEmpty() ) {
		setExpandable( true );
		repaint();
	}

	listView()->setUpdatesEnabled( true );
}

PortItem::PortItem( KListView *parent, const Port &port )
	: KListViewItem( parent ),
	m_port( port )
{
	init();
}

PortItem::PortItem( CategoryItem *parent, const Port &port )
	: KListViewItem( parent ),
	m_port( port )
{
	init();
}

void PortItem::init()
{
	setText( 0, m_port.name() );
	setText( 1, m_port.version() );
}

PortSelectCommand::PortSelectCommand() : Command(),
	m_parent( 0 ),
	m_oldItem( 0 ),
	m_newItem( 0 )
{
}

void PortSelectCommand::setup( PortListView *parent, QListViewItem *oldItem,
                               QListViewItem *newItem )
{
	m_parent = parent;
	m_oldItem = oldItem;
	m_newItem = newItem;
}

void PortSelectCommand::selectItem( QListViewItem *item )
{
	if ( !m_parent || !item )
		return;

	m_parent->setCurrentItem( item );
	m_parent->ensureItemVisible( item );

	item->setOpen( !item->isOpen() );

	PortItem *port = dynamic_cast<PortItem *>( item );
	if ( port )
		emit m_parent->portSelected( port->port() );
}

void PortSelectCommand::doExec()
{
	selectItem( m_newItem );
}

void PortSelectCommand::doUnexec()
{
	selectItem( m_oldItem );
}

QString PortSelectCommand::text() const
{
	QListViewItem *item = executed() ? m_oldItem : m_newItem;
	if ( PortItem *portItem = dynamic_cast<PortItem *>( item ) )
		return i18n( "Port '%1'" ).arg( portItem->port().name() );
	return i18n( "Category '%1'" ).arg( item->text( 0 ) );
}

PortListView::PortListView( QWidget *parent )
	: KListView( parent, "PortListView" ),
	m_oldItem( 0 )
{
	connect( this, SIGNAL( executed( QListViewItem * ) ),
	         this, SLOT( itemSelected( QListViewItem * ) ) );
	connect( this, SIGNAL( returnPressed( QListViewItem * ) ),
	         this, SLOT( itemSelected( QListViewItem * ) ) );
	
	setRootIsDecorated( true );
	setAllColumnsShowFocus( true );
	setShowSortIndicator( true );

	addColumn( i18n( "Name" ) );
	setColumnWidthMode( 0, QListView::Manual );
	setColumnWidth( 0, 200 );

	addColumn( i18n( "Version" ) );
	setColumnWidthMode( 1, QListView::Manual );
	setColumnWidth( 1, 100 );
}

void PortListView::populate()
{
	clear();

	const QStringList categories = PortMgr::self().categories();
	QStringList::ConstIterator it = categories.begin();
	QStringList::ConstIterator end = categories.end();
	for ( ; it != end; ++it )
		new CategoryItem( this, *it );
}

void PortListView::selectPort( const QString &port )
{
	PortItem *curPortItem = dynamic_cast<PortItem *>( currentItem() );
	if ( curPortItem && curPortItem->port().name() == port )
		return;

	if ( m_nameDict.find( port ) == 0 )
		return;
	itemSelected( m_nameDict[ port ] );
}

void PortListView::selectPort( const Port &port )
{
	PortItem *curPortItem = dynamic_cast<PortItem *>( currentItem() );
	if ( curPortItem && curPortItem->port() == port )
		return;

	if ( !m_portMap.contains( port ) )
		return;
	itemSelected( m_portMap[ port ] );
}

void PortListView::itemSelected( QListViewItem *item )
{
	PortSelectCommand *cmd = 0;
	if ( m_oldItem )
		cmd = Command::create<PortSelectCommand>( Command::Register );
	else
		cmd = Command::create<PortSelectCommand>();
	cmd->setup( this, m_oldItem, item );
	cmd->exec();

	m_oldItem = item;
}

#include "portlistview.moc"
// vim:ts=4:sw=4:noet:list
