/***************************************************************************
                          dcwidget.cpp  -  description
                             -------------------
    begin                : Don Mai 30 2002
    copyright            : (C) 2002-2005 by Mathias Küster
    email                : mathen@users.berlios.de
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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 option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

#include "dcwidget.h"

#include <QApplication>
#include <QStyle>
#include <QPainter>
#include <Q3Header>
#include <QPixmap>
#include <QStyleOption>
#include <QProgressBar>
#include <QBrush>

#include <Q3ListViewItemIterator>

#include "dctransferview.h"
#include "dcconfig.h"

#include <dclib/dcos.h>

#define DC_QProgressListItemRTTI 3000

#include "search-result-columns.h"

/** */
int DC_QListViewItem::compare( Q3ListViewItem * i, int col, bool ascending ) const
{
	if(col==DC_QNumericSortItem::mycol)
		return DC_QNumericSortItem::mycompare(((DC_QListViewItem*)i)->myvalue);
	else
		return Q3ListViewItem::compare(i,col,ascending);
}

/** */
int DC_QNumericSortItem::mycompare( ulonglong other ) const
{
	if ( myvalue < other ) return -1;
	else if ( myvalue == other ) return 0;
	else return 1;
}

/** */
QString DC_QListViewItem::key( int column, bool /*ascending*/ ) const
{
	return text( column ).toLower();
}

/** */
void DC_ListResult::paintCell( QPainter * p, const QColorGroup & cg, int column, int width, int align )
{
	QColorGroup _cg( cg );
	QColor c = ((QPalette)_cg).text().color();
	QBrush br = _cg.brush(QColorGroup::Base);
	QColor cl(br.color());

	cl.setRed(int(cl.red()*0.8f+30.0f));
	cl.setGreen(int(cl.green()*0.8f+30.0f));
	cl.setBlue(int(cl.blue()*0.8f+30.0f));

	this->cg = cg;

	int my_index = 0;
	int parent_index = 0;

	if (parent()){
	    DC_ListResult *item = (DC_ListResult *)parent();

	    Q3ListViewItem::paintCell(p, item->cg, column, width, align);

	    return;
	}

	Q3ListViewItemIterator it(this->listView(), Q3ListViewItemIterator::Visible);
	while (it.current()) {
	    if ((*it) == this)
		break;
	    if (it.current()->firstChild())
		my_index++;
	    ++it;
	}

	if (group_item && g_pConfig->GetAlternatingRowColors()){
		if ((my_index % 2) == 0){
		    _cg.setColor(QColorGroup::Base, cl);
		}
	}

        if (exists){
	   _cg.setColor(QColorGroup::Text, QColor(0x00, 0x80, 0x80));

	   this->cg = _cg;

           Q3ListViewItem::paintCell(p, _cg, column, width, align);

           return;

        }
        
        if ( column == RESULTS_COLUMN_NICK )
        {
                if ( g_pTransferView->IsUserInQueue( text(RESULTS_COLUMN_NICK), text(RESULTS_COLUMN_HUB) ) )
                {
                        _cg.setColor( QColorGroup::Text, Qt::blue );

                        Q3ListViewItem::paintCell( p, _cg, column, width, align );

                        return;
                }

        }

	if (group_item && g_pConfig->GetAlternatingRowColors()){
	    if ((my_index % 2) == 0){
		_cg.setColor(QColorGroup::Base, cl);

		this->cg = _cg;

		Q3ListViewItem::paintCell( p, _cg, column, width, align );

		return;
	    }
	}

        Q3ListViewItem::paintCell( p, cg, column, width, align );
	
}

/** Re-implemented to fix sorting search results by slots columns */
QString DC_ListResult::key( int column, bool ascending ) const
{
	if ( (column == RESULTS_COLUMN_FREESLOTS) || (column == RESULTS_COLUMN_TOTALSLOTS) )
	{
		//printf("Key=%s\n",(text( column ).rightJustify( 5, '0' )).ascii() );
		return text( column ).rightJustified( 5, '0' );
	}
	else
	{
		return DC_QListViewItem::key( column, ascending );
	}
}

/** */
DC_QProgressListItem::DC_QProgressListItem( DC_QProgressListItem * parent, int co )
    : Q3ListViewItem( parent )
{
	m_nColumn = co;
	init();
}

/** */
DC_QProgressListItem::DC_QProgressListItem( Q3ListViewItem * parent, int co )
    : Q3ListViewItem( parent )
{
	m_nColumn = co;
	init();
}

/** */
DC_QProgressListItem::DC_QProgressListItem( Q3ListView * parent, int co )
    : Q3ListViewItem( parent )
{
	m_nColumn = co;
	init();
}

/** */
int DC_QProgressListItem::rtti() const
{
	return DC_QProgressListItemRTTI;
}

/** */
void DC_QProgressListItem::init()
{
	// init progress bar
	m_ProgressBar = new QProgressBar(0);
	m_ProgressBar->setTextVisible(true);
	m_bProgressEnable = true;
	//m_ProgressBar->setIndicatorFollowsStyle(false);
	resetProgress();
}

/** */
void DC_QProgressListItem::resetProgress()
{
	m_ProgressBar->reset();
	m_ProgressBar->setRange(0, 100);
	//m_ProgressBar->setTotalSteps(100);
}

/** */
void DC_QProgressListItem::setProgress( int i )
{
	m_ProgressBar->setValue(i);
}

/** */
DC_QProgressListItem::~DC_QProgressListItem()
{
	delete m_ProgressBar;
}

/** */
void DC_QProgressListItem::setup()
{
	Q3ListViewItem::setup();
	int h = Q3ListViewItem::height();
	//h = QMAX( listView()->style().pixelMetric(QStyle::PM_ProgressBarChunkWidth, listView()), h );
	//h = QMAX( h, QApplication::globalStrut().height() );
	setHeight( h );
	m_ProgressBar->setFixedHeight(h-listView()->itemMargin());
	m_ProgressBar->setFixedWidth(160);
}

/** */
int DC_QProgressListItem::width( const QFontMetrics& fm, const Q3ListView* lv, int column) const
{
	int r = Q3ListViewItem::width( fm, lv, column );
	if ( (column == m_nColumn) && m_bProgressEnable ) {
		r += lv->itemMargin();
		
		QStyleOptionProgressBarV2 qso;
		qso.initFrom( m_ProgressBar );
		r +=  lv->style()->pixelMetric(QStyle::PM_ProgressBarChunkWidth, &qso, lv) + 4;
	}

	return QMAX( r, QApplication::globalStrut().width() );
}

/*!
    Paints the item using the painter \a p and the color group \a cg.
    The item is in column \a column, has width \a width and has
    alignment \a align. (See Qt::AlignmentFlags for valid alignments.)
*/
void DC_QProgressListItem::paintCell( QPainter * p, const QColorGroup & cg,
			       int column, int width, int align )
{
	if ( !p )
		return;

	Q3ListView *lv = listView();
	if ( !lv )
		return;

	//const Qt::BackgroundMode bgmode = lv->viewport()->backgroundMode();
	const QColorGroup::ColorRole crole = lv->viewport()->backgroundRole(); //QPalette::backgroundRoleFromMode( bgmode );

	// we are not friends ...
//	if ( cg.brush( crole ) != lv->colorGroup().brush( crole ) )
		p->fillRect( 0, 0, width, Q3ListViewItem::height(), cg.brush( crole ) );
//	else
//		paintEmptyArea( p, QRect( 0, 0, width, QListViewItem::height() ) );

	if ( (column != m_nColumn) || (m_bProgressEnable == false) )
	{
		// The rest is text, or for subclasses to change.
		Q3ListViewItem::paintCell( p, cg, column, width, align );
		return;
	}

	int r = lv->itemMargin();

	QStyleOptionProgressBarV2 styleoption;
	styleoption.initFrom( m_ProgressBar );
	styleoption.maximum       = m_ProgressBar->maximum();
	styleoption.minimum       = m_ProgressBar->minimum();
	styleoption.progress      = m_ProgressBar->value();
	styleoption.text          = m_ProgressBar->text();
	styleoption.textAlignment = m_ProgressBar->alignment();
	styleoption.textVisible   = m_ProgressBar->isTextVisible();
	styleoption.rect          = m_ProgressBar->contentsRect();

	if ( isSelected() )
	{
		styleoption.state = styleoption.state | QStyle::State_Selected;
	}
	
	if ( Q3ListViewItem::isEnabled() && lv->isEnabled() )
	{
		styleoption.state = styleoption.state | QStyle::State_Enabled;
	}

	p->save();

	m_ProgressBar->style()->drawControl(QStyle::CE_ProgressBar, &styleoption, p, m_ProgressBar);

	r += m_ProgressBar->width();

	p->restore();

	p->translate( r, 0 );
	p->setBrush( ((QPalette)cg).text() );
	Q3ListViewItem::paintCell( p, cg, column, width - r, align );
}

/*!
    Draws the focus rectangle \a r using the color group \a cg on the
    painter \a p.
*/
void DC_QProgressListItem::paintFocus( QPainter *p, const QColorGroup & cg,
				 const QRect & r )
{
	bool intersect = true;
	Q3ListView *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( QRect( p, r.y(), xdepth - p + 1, r.height() ) );
	}

	if ( intersect )
	{
		QRect rect;
		int boxsize = 0; //lv->style().pixelMetric(QStyle::PM_ProgressBarChunkWidth, lv);
		if ( lv->columnAlignment(0) == Qt::AlignCenter )
		{
			QFontMetrics fm( lv->font() );
			int bx = (lv->columnWidth(0) - (boxsize + fm.width(text(0))))/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() );
		Q3ListViewItem::paintFocus(p, cg, rect);
	}
	else
	{
		Q3ListViewItem::paintFocus(p, cg, r);
	}
}

/** Returns the key used to sort the items.
 *  If the progress bar is enabled, we return a key like d069 or u071
 *  The initial letter stands for download or upload etc., the number is the percentage of the transfer.
 *  If the progress bar is not enabled or the column isn't the transfer column, returns QListViewItem::key() .
 *  QT Docs say ascending parameter can be ignored. 
 */
QString DC_QProgressListItem::key( int n, bool ascending ) const
{
	// printf("DC_QProgessListItem::key called for column: %d\n", n);
	
	// column 2 is Transfer column
	if ( (n == 2) && (m_bProgressEnable) )
	{
		QString s;
		s.setNum(m_ProgressBar->value()).rightJustified(3, '0');
		s.prepend(sTransferState);
		//printf("Key for sorting transfer column is %s\n", s.toAscii().constData());
		return s;
	}
	else
	{
		return Q3ListViewItem::key( n, ascending );
	}
}

/** */
void DC_QProgressListItem::setTransferState( QString s )
{
	sTransferState = s;
}
