/***************************************************************************
                          dctransferview.cpp  -  description
                             -------------------
    begin                : Sat Feb 23 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 <q3listview.h>
#include <qcursor.h>
#include <qtabwidget.h>
#include <qmessagebox.h>
#include <QTextEdit>
#include <qdatetime.h>
#include <qinputdialog.h>
#include <qtimer.h>
#include <QMdiArea>
#include <qcombobox.h>
#include <qregexp.h>
#include <qlayout.h>
//Added by qt3to4:
#include <QKeyEvent>
#include <QGridLayout>
#include <QResizeEvent>
#include <QEvent>
#include <QHeaderView>

#include "dcconfig.h"
#include "dcfilebrowser.h"
#include "dcconnectionmanager.h"
#include "dcmenuhandler.h"
#include "dcfiletransferinfo.h"
#include "dcevent.h"

#include "dctransferview.h"
#include "dchubsearch.h"
#include "dcedittransfer.h"
#include "dciconloader.h"

#include <dclib/cdownloadqueue.h>
#include <dclib/cdownloadmanager.h>
#include <dclib/dcos.h>
#include <dclib/cutils.h>
#include <dclib/cfilemanager.h>

#define TIMER_BASE 500

DCTransferView * g_pTransferView = 0;

/** */
DCTransferView::DCTransferView(QWidget* parent, const char *name, Qt::WindowFlags wflags) : QWidget(parent, name, wflags)
{
	int idx;

	setupUi(this);

	// set default icon
	setIcon( g_pIconLoader->GetPixmap(eiTRANSFER) );

	// set the ColumnWidthMode to manual, we will take care of this task
	for( idx = 0; idx < ListView_TRANSFER->columns(); idx++ )
	{
		ListView_TRANSFER->setColumnWidthMode( idx, Q3ListView::Manual );
	}
	for( idx = 0; idx < ListView_TRANSFERWAIT->columns(); idx++ )
	{
		ListView_TRANSFERWAIT->setColumnWidthMode( idx, Q3ListView::Manual );
	}
	for( idx = 0; idx < ListView_LOCALFILES->columns(); idx++ )
	{
		ListView_LOCALFILES->setColumnWidthMode( idx, Q3ListView::Manual );
	}
	for( idx = 0; idx < TreeWidget_SLOTS->columnCount(); idx++ )
	{
		TreeWidget_SLOTS->header()->setResizeMode( idx, QHeaderView::Interactive );
	}

	TreeWidget_SLOTS->sortByColumn( 0, Qt::AscendingOrder );

	pFileList         = new CList<DCFileBrowser>();
	pMessageList      = new CList<CObject>;
	pQueueList        = new CThreadStringList();
	pQueueLocalList   = new CThreadStringList();
	pViewTransferList = new CThreadStringList();

	Timer = new QTimer;
	Thread = new CThread;

	InitDocument();

	g_pTransferView = this;
}

/** */
DCTransferView::~DCTransferView()
{
	DCFileBrowser * FileList;

	g_pTransferView = NULL;

	ListView_TRANSFERWAIT->removeEventFilter(this);
	removeEventFilter(ListView_TRANSFERWAIT);

	if ( Timer )
	{
		Timer->stop();
		delete Timer;
	}

	Thread->Lock();

	// clear filelist
	while ( (FileList=pFileList->Next(0)) != 0 )
	{
		// remove from the list
		pFileList->Remove(FileList);
		delete FileList;
	}

	delete pFileList;
	pFileList = 0;

	ListView_TRANSFERWAIT->clear();
	ListView_LOCALFILES->clear();

	if ( pMessageList )
	{
		delete pMessageList;
		pMessageList = 0;
	}

	if ( pQueueList )
	{
		delete pQueueList;
		pQueueList = 0;
	}

	if ( pQueueLocalList )
	{
		delete pQueueLocalList;
		pQueueLocalList = 0;
	}

	if ( pViewTransferList )
	{
		delete pViewTransferList;
		pViewTransferList = 0;
	}

	DLM_SaveQueue();

	Thread->UnLock();

	delete Thread;
	Thread = 0;
}

/** */
void DCTransferView::SetMdiArea( QMdiArea* mdiarea )
{
	pMdiArea = mdiarea;
}

/** */
void DCTransferView::InitDocument()
{
	StringMap * map;

	// on create set tab width
	ResizeListViewColumn();

	// init log tab
	QGridLayout * tll = new QGridLayout( Frame_LOG, 1, 1, 4, 4, "tabLayoutLog");
	m_pTextEdit_LOG = new QTextEdit( Frame_LOG );
	m_pTextEdit_LOG->setReadOnly( TRUE );
	m_pTextEdit_LOG->document()->setMaximumBlockCount( 300 );
	m_pTextEdit_LOG->setContextMenuPolicy( Qt::CustomContextMenu );
	tll->addWidget( m_pTextEdit_LOG, 0, 0 );

	// install event filters
	ListView_TRANSFERWAIT->installEventFilter(this);
	installEventFilter(ListView_TRANSFERWAIT);

	// default setting
	if ( g_pConfig->GetMap("TRANSFERVIEW",map) == FALSE )
	{
		// view is docked
		(*map)["DOCKED"] = QString("1");
	}

	connect( TabWidget_TRANSFER,SIGNAL(currentChanged(QWidget*)), this, SLOT(slotTabWidgetCurrentChange(QWidget*)) );
	connect( ListView_TRANSFER, SIGNAL(contextMenuRequested( Q3ListViewItem *, const QPoint &, int )), this, SLOT(slotRightButtonClickedTransferList(Q3ListViewItem*, const QPoint &, int )) );
	connect( ListView_TRANSFERWAIT, SIGNAL(contextMenuRequested( Q3ListViewItem *, const QPoint &, int )), this, SLOT(slotRightButtonClickedTransferWaitList(Q3ListViewItem*, const QPoint &, int )) );
	connect( ListView_LOCALFILES, SIGNAL(contextMenuRequested( Q3ListViewItem *, const QPoint &, int )), this, SLOT(slotRightButtonClickedLocalFilesList(Q3ListViewItem*, const QPoint &, int )) );
	connect( ListView_TRANSFERWAIT,SIGNAL(doubleClicked(Q3ListViewItem*)), this, SLOT(slotDoubleClickedTransferWaitList(Q3ListViewItem*)) );
	connect( TreeWidget_SLOTS, SIGNAL(customContextMenuRequested( const QPoint & )), this, SLOT(slotContextMenuUserSlotList( const QPoint & )) );
	connect( m_pTextEdit_LOG, SIGNAL(customContextMenuRequested( const QPoint & )), this, SLOT(slotRightButtonClickedLog( const QPoint & )) );

	connect( Timer, SIGNAL(timeout()), this, SLOT(timerDone()) );

	Timer->start( TIMER_BASE, TRUE );
}

/** */
void DCTransferView::DeInitDocument()
{
	// deinit transferview
	// StringMap * map;

	// save hub view settings
	// g_pConfig->GetMap("HUBVIEW",map);
}

/** */
bool DCTransferView::eventFilter( QObject * object, QEvent * event )
{
	DCFileBrowser * FileList;

	if( (event->type() == QEvent::Close) &&
	    ((DCTransferView*)object!=this) &&
	    ((Q3ListView*)object!=ListView_TRANSFERWAIT) )
	{
		// file list closed
		Thread->Lock();

		if ( pFileList != 0 )
		{
			((DCFileBrowser *)object)->showNormal();
			FileList = (DCFileBrowser *)object;
			pFileList->Remove(FileList);
		}

		Thread->UnLock();
	}
	else if ((event->type() == QEvent::KeyPress)&&((Q3ListView*)object==ListView_TRANSFERWAIT))
	{
		QKeyEvent * e = (QKeyEvent*)event;
		
		if ( e->key() == Qt::Key_Delete )
		{
		}
	}

	return QWidget::eventFilter( object, event );    // standard event processing
}

/** current tab widget change slot */
void DCTransferView::slotTabWidgetCurrentChange(QWidget*)
{
//	ResizeListViewColumn();
}

/** overridden so that the columns are resized on show() */
void DCTransferView::show()
{
	QWidget::show();

	ResizeListViewColumn();
}

/** resize event handler */
void DCTransferView::resizeEvent( QResizeEvent * )
{
	ResizeListViewColumn();
}

/** resize the ListView columns */
void DCTransferView::ResizeListViewColumn()
{
	int width = 0;

	if ( ListView_TRANSFER->isVisible() )
	{
		width = ListView_TRANSFER->width();
	}
	else if ( ListView_TRANSFERWAIT->isVisible() )
	{
		width = ListView_TRANSFERWAIT->width();
	}
	else if ( ListView_LOCALFILES->isVisible() )
	{
		width = ListView_LOCALFILES->width();
	}
	else if ( TreeWidget_SLOTS->isVisible() )
	{
		width = TreeWidget_SLOTS->width();
	}

	if ( width > 0 )
	{
		ListView_TRANSFER->setColumnWidth( 0, ((width*1)/7) );
		ListView_TRANSFER->setColumnWidth( 1, ((width*1)/7) );
		ListView_TRANSFER->setColumnWidth( 2, ((width*3)/7) );
		ListView_TRANSFER->setColumnWidth( 3, ((width*2)/7) );
		//ListView_TRANSFER->setColumnWidth( 4, ((width*2)/9) );

		ListView_TRANSFERWAIT->setColumnWidth( 0, ((width*4 )/24) );
		ListView_TRANSFERWAIT->setColumnWidth( 1, ((width*11)/24) );
		ListView_TRANSFERWAIT->setColumnWidth( 2, ((width*5 )/24) );
		ListView_TRANSFERWAIT->setColumnWidth( 3, ((width*4 )/24) );

		ListView_LOCALFILES->setColumnWidth( 0, ((width*5)/11) );
		ListView_LOCALFILES->setColumnWidth( 1, ((width*2)/11) );
		ListView_LOCALFILES->setColumnWidth( 2, ((width*3)/11) );
		ListView_LOCALFILES->setColumnWidth( 1, ((width*3)/11) );

		TreeWidget_SLOTS->header()->resizeSection( 0, ((width*3)/9) );
		TreeWidget_SLOTS->header()->resizeSection( 1, ((width*3)/9) );
		TreeWidget_SLOTS->header()->resizeSection( 2, ((width*3)/9) );
	}
}

/** download manager callback function */
int DCTransferView::DC_DownloadManagerCallBack( CObject * Object )
{
	int err = -1;

	if ( Thread == 0 )
	{
		return err;
	}
	
	Thread->Lock();

	if ( Object != NULL )
	{
		if ( pMessageList != 0 )
		{
			pMessageList->Add(Object);
			err = 0;
		}
		else
		{
			err = -1;
		}
        }
	else
	{
		err = -1;
	}

	Thread->UnLock();

	return err;
}

/** */
void DCTransferView::timerDone()
{
	CObject * Object;
	CDCMessage *DCMsg;
	bool bLVWaitUpdate = FALSE;
	int i;

	for(i=0;i<50;i++)
	{
		if ( Thread->TryLock() == FALSE )
		{
			break;
		}

		if ( pMessageList != 0 )
		{
			Object = pMessageList->Next(0);

			if ( Object != 0 )
			{
				pMessageList->Remove(Object);
			}
		}
		else
		{
			Object = 0;
		}

		Thread->UnLock();

		if ( Object == 0 )
		{
			break;
		}

		DCMsg = (CDCMessage*) Object;

		switch ( DCMsg->m_eType )
		{
			case DC_MESSAGE_DM_INFO:
			{
				CDownloadManagerInfo * msg = (CDownloadManagerInfo*)Object;

				QApplication::postEvent( this, new DC_DownloadManagerEvent( EVENT_UPDATE_DM_STATUSBAR, msg ) );

				break;
			}

			case DC_MESSAGE_FM_INFO:
			{
				CFileManagerInfo * msg = (CFileManagerInfo*)Object;

				QApplication::postEvent( this, new DC_FileManagerEvent( EVENT_UPDATE_FM_STATUSBAR, msg ) );

				break;
			}

			case DC_MESSAGE_TRAFFIC:
			{
				DCMessageTraffic * msg = (DCMessageTraffic*)Object;

				QApplication::postEvent( this, new DC_TrafficInfoEvent( EVENT_UPDATE_TR_STATUSBAR, msg ) );

				break;
			}

			case DC_MESSAGE_SLOT_OBJECT:
			{
				MessageSlot( (CMessageDMSlotObject *)Object );
				break;
			}

			case DC_MESSAGE_LOG:
			{
				MessageLog( (CMessageLog*)Object );

				break;
			}

			case DC_MESSAGE_FILE_OBJECT:
			{
				CMessageDMFileObject * msg = (CMessageDMFileObject*)Object;

				// must be called BEFORE UpdateTransferWaitList
				UpdateLocalFileList( msg );

				if ( UpdateTransferWaitList( msg ) == TRUE )
				{
					bLVWaitUpdate = TRUE;
				}

				break;
			}

			case DC_MESSAGE_TRANSFER_OBJECT:
			{
				MessageTransfer( (CMessageDMTransferObject*)Object );

				break;
			}

			case DC_MESSAGE_FILELIST_OBJECT:
			{
				CMessageDMFileListObject * msg = (CMessageDMFileListObject*)Object;

				NewFileBrowser(msg->sNick.Data(),msg->sHubName.Data(),msg->sHubHost.Data(),msg->sLocalFile.Data());

				break;
			}

			default:
			{
				break;
			}
		}

		if ( Object )
		{
			delete Object;
		}
	}

	if ( bLVWaitUpdate == TRUE )
	{
		ListView_TRANSFERWAIT->setUpdatesEnabled(TRUE);
		ListView_TRANSFERWAIT->triggerUpdate();
	}

	Timer->start( TIMER_BASE, TRUE );
}

/** */
void DCTransferView::MessageSlot( CMessageDMSlotObject * msg )
{
	int index = 0;
	QTreeWidgetItem * item = TreeWidget_SLOTS->topLevelItem( index );

	while(item)
	{
		if ( (item->text(0) == msg->sNick.Data()) &&
		     (item->text(1) == msg->sHubName.Data()) )
		{
			if ( (msg->iSlots == 0) && (!msg->bPermanent) )
			{
				delete item;
				item=0;
			}

			break;
		}

		index++;
		item = TreeWidget_SLOTS->topLevelItem( index );
	}

	if ( (!item) && ((msg->iSlots > 0) || (msg->bPermanent)) )
	{
		item = new QTreeWidgetItem( TreeWidget_SLOTS );
		item->setText( 0, msg->sNick.Data() );
		item->setText( 1, msg->sHubName.Data() );
	}

	if (item)
	{
		if ( msg->bPermanent )
		{
			item->setText(2,"X");
		}
		else
		{
			item->setText(2,QString().setNum(msg->iSlots));
		}
	}
}

/** */
void DCTransferView::MessageLog( CMessageLog * msg )
{
	bool bscroll;

	if ( m_pTextEdit_LOG->verticalScrollBar()->maximum() == m_pTextEdit_LOG->verticalScrollBar()->value() )
	{
		bscroll = TRUE;
	}
	else
	{
		bscroll = FALSE;
	}

	m_pTextEdit_LOG->append( QTime::currentTime().toString("[hh:mm:ss] ") + QString(msg->sMessage.Data()) );

	if ( bscroll )
	{
		// QT3 m_pTextEdit_LOG->scrollToBottom();
		// QT3 m_pTextEdit_LOG->moveCursor( Q3TextEdit::MoveEnd, FALSE );
		QTextCursor cursor = m_pTextEdit_LOG->textCursor();
		cursor.movePosition( QTextCursor::End, QTextCursor::MoveAnchor, 1 );
		m_pTextEdit_LOG->setTextCursor(cursor);
	}
}

/** */
void DCTransferView::MessageTransfer( CMessageDMTransferObject * msg )
{
	CMessageDMTransferObject * msg1 = 0;
				
	CString s;
	QString n;
	DCTransferListItem * TransferListItem = 0;

	pViewTransferList->Lock();

	if ( pViewTransferList->Get( CString().setNum(msg->m_nTransferID), (CObject*&)TransferListItem ) != 0 )
	{
		if ( msg->bRemoveTransfer == FALSE )
		{
			// create new entry
			TransferListItem = new DCTransferListItem();
			TransferListItem->pItem = new DC_QProgressListItem( ListView_TRANSFER, "", 2 );

			if ( msg->m_bEncrypted )
//				TransferListItem->pItem->setPixmap(0,QPixmap(ssl_no_xpm));
//			else
				TransferListItem->pItem->setPixmap(0,g_pIconLoader->GetPixmap(eiSSL_YES));

			if ( !g_pConfig->GetTransferViewOptions(etvoFILEPERCENT) )
			{
				TransferListItem->pItem->SetProgressEnable(FALSE);
			}
			
			TransferListItem->pObject = new CMessageDMTransferObject();
						
			msg1 = (CMessageDMTransferObject *)TransferListItem->pObject;
			// set transfer id
			msg1->m_nTransferID = msg->m_nTransferID;

			pViewTransferList->Add( CString().setNum(msg->m_nTransferID), TransferListItem );
		}
		else
		{
			pViewTransferList->UnLock();
			return;
		}
	}
	else if ( msg->bRemoveTransfer == TRUE )
	{
		ListView_TRANSFER->takeItem(TransferListItem->pItem);
		delete TransferListItem->pItem;
		delete TransferListItem->pObject;
		pViewTransferList->Del(CString().setNum(msg->m_nTransferID));
		pViewTransferList->UnLock();
		return;
	}

	msg1 = (CMessageDMTransferObject *)TransferListItem->pObject;

	//
	if ( msg1->m_bEncrypted != msg->m_bEncrypted )
	{
		msg1->m_bEncrypted = msg->m_bEncrypted;

		if ( msg->m_bEncrypted )
//			TransferListItem->pItem->setPixmap(0,QPixmap(ssl_no_xpm));
//		else
			TransferListItem->pItem->setPixmap(0,g_pIconLoader->GetPixmap(eiSSL_YES));
	}

	// update transfer state
	if ( msg1->eState != msg->eState )
	{
		msg1->eState = msg->eState;
		
		switch(msg1->eState)
		{
			case estTRANSFERDOWNLOAD:
				TransferListItem->pItem->setPixmap(2,g_pIconLoader->GetPixmap(eiDOWN));
				TransferListItem->pItem->setTransferState("d");
				//TransferListItem->pItem->setText(3,tr("Download"));
				break;
			case estTRANSFERUPLOAD:
				TransferListItem->pItem->setPixmap(2,g_pIconLoader->GetPixmap(eiUP));
				TransferListItem->pItem->setTransferState("u");
				//TransferListItem->pItem->setText(3,tr("Upload"));
				break;
			case estTRANSFERHANDSHAKE:
				TransferListItem->pItem->setPixmap(2,g_pIconLoader->GetPixmap(eiBACK));
				TransferListItem->pItem->setTransferState("h");
				//TransferListItem->pItem->setText(3,tr("Handshake"));
				break;
			case estNONE:
				//TransferListItem->pItem->setText(3,tr("Nothing"));
				TransferListItem->pItem->setTransferState("n");
				break;
			default:
				TransferListItem->pItem->setPixmap(2,g_pIconLoader->GetPixmap(eiHELP));
				TransferListItem->pItem->setTransferState("q");
				//TransferListItem->pItem->setText(3,tr("Unknown"));
				break;
		}
	}

	// update nick
	if ( msg1->m_sDstNick != msg->m_sDstNick )
	{
		msg1->m_sDstNick = msg->m_sDstNick;
		//TransferListItem->pItem->setText( 0, msg->m_sDstNick.Data() );
		if ( msg1->sHost != msg->sHost )
			msg1->sHost    = msg->sHost;

		n  = msg1->m_sDstNick.Data();
		n += " (";
		n += msg1->sHost.Data();
		n += ")";

		TransferListItem->pItem->setText(0, n );
	}
	// update user host
	else if ( msg1->sHost != msg->sHost )
	{
		msg1->sHost    = msg->sHost;
		
		n  = msg1->m_sDstNick.Data();
		n += " (";
		n += msg1->sHost.Data();
		n += ")";

		TransferListItem->pItem->setText(0, n );
	}

	// update hub
	if ( msg1->sHubName != msg->sHubName )
	{
		msg1->sHubName = msg->sHubName;

		TransferListItem->pItem->setText(1, msg1->sHubName.Data() );
	}

	// update hubhost
	if ( msg1->m_sHubHost != msg->m_sHubHost )
	{
		msg1->m_sHubHost = msg->m_sHubHost;
	}
				
	// update filename
	if ( msg1->m_sSrcFile != msg->m_sSrcFile )
	{
		TransferListItem->pItem->resetProgress();
		QString meh = msg->m_sSrcFile.Data();
		if ( meh.contains( '\\', FALSE ) > 0 )
			meh = meh.mid( meh.findRev( '\\' )+1, meh.length() );
		else if ( meh.contains( '/', FALSE ) > 0 )
			meh = meh.mid( meh.findRev( '/' )+1, meh.length() );
		TransferListItem->pItem->setText( 3, meh );
	}

	// update remote filename + path
	if ( msg1->m_sDstFile != msg->m_sDstFile )
	{
		msg1->m_sDstFile = msg->m_sDstFile;
		TransferListItem->pItem->resetProgress();
		TransferListItem->pItem->setText( 4, msg->m_sDstFile.Data() );
	}

	// update local filename
	if ( msg1->m_sSrcFile != msg->m_sSrcFile )
	{
		msg1->m_sSrcFile = msg->m_sSrcFile;
		TransferListItem->pItem->resetProgress();
		TransferListItem->pItem->setText( 5, msg->m_sSrcFile.Data() );
	}

	// update transfer rate
	if ( (msg1->lRate != msg->lRate) ||
	     (msg1->m_nMultiRate != msg->m_nMultiRate) ||
	     (msg1->lSize != msg->lSize) ||
	     (msg1->lSizeDone != msg->lSizeDone) ||
	     (msg1->lStartPosition != msg->lStartPosition) ||
	     (msg1->lTransfered != msg->lTransfered) ||
	     (msg1->lEndPosition != msg->lEndPosition) )
	{
		msg1->lRate = msg->lRate;
		msg1->m_nMultiRate = msg->m_nMultiRate;
		msg1->lSize = msg->lSize;
		msg1->lSizeDone = msg->lSizeDone;
		msg1->lStartPosition = msg->lStartPosition;
		msg1->lTransfered = msg->lTransfered;
		msg1->lEndPosition = msg->lEndPosition;
		
		s = "";

		if ( g_pConfig->GetTransferViewOptions(etvoCHUNKPERCENT) )
		{
			if ( (msg1->lEndPosition-msg1->lStartPosition) != 0 )
			{
				s += CString().setNum(((msg1->lTransfered)*100)/(msg1->lEndPosition-msg1->lStartPosition));
				s += "% ";
			}
			else
			{
				s += "0% ";
			}
		}

		if ( g_pConfig->GetTransferViewOptions(etvoFILEPERCENT) )
		{
			TransferListItem->pItem->SetProgressEnable(TRUE);
			if ( msg1->lSize != 0 )
			{
				TransferListItem->pItem->setProgress( (msg1->lSizeDone*100)/msg1->lSize );
			}
			else
			{
				TransferListItem->pItem->setProgress( 0 );
			}

/*			if ( msg1->lSize != 0 )
			{
				s += CString().setNum(((msg1->lSizeDone)*100)/msg1->lSize);
				s += "% ";
			}
			else
			{
					s += "0% ";
			}
*/
		}
		else
		{
			TransferListItem->pItem->SetProgressEnable(FALSE);
		}
		
		if ( g_pConfig->GetTransferViewOptions(etvoCHUNKSIZE) )
		{
			s += " ";
			// s += CString().setNum(msg->lStartPosition);
			s += CUtils::GetSizeString(msg->lStartPosition,g_pConfig->GetUnit()).Data();
			s += "/";
			// s += CString().setNum(msg->lStartPosition+msg->lTransfered);
			s += CUtils::GetSizeString(msg->lStartPosition+msg->lTransfered,g_pConfig->GetUnit());
			s += "/";
			// s += CString().setNum(msg->lEndPosition);
			s += CUtils::GetSizeString(msg->lEndPosition,g_pConfig->GetUnit()).Data();
		}

		if ( g_pConfig->GetTransferViewOptions(etvoFILESIZE) )
		{
			s += " ";
			// s += CString().setNum(msg->lSizeDone);
			s += CUtils::GetSizeString(msg->lSizeDone,g_pConfig->GetUnit()).Data();
			s += "/";
			// s += CString().setNum(msg->lSize);
			s += CUtils::GetSizeString(msg->lSize,g_pConfig->GetUnit()).Data();
		}

		if ( g_pConfig->GetTransferViewOptions(etvoDOWNLOADRATESINGLE) )
		{
			ulonglong rate;

			rate = msg->lRate;

			s += " [";
			s += CUtils::GetTransferString(rate);
			s += "]";
		}

		if ( g_pConfig->GetTransferViewOptions(etvoELAPSEDTIMESINGLE) )
		{
			ulonglong rate = 0;

			rate = msg1->lSize-msg1->lSizeDone;

			if ( msg->lRate>0 )
				rate/=msg->lRate;

			s += " [";
			s += CUtils::GetTimeString(rate);
			s += "]";
		}

		if ( g_pConfig->GetTransferViewOptions(etvoDOWNLOADRATEMULTI) )
		{
			ulonglong rate;

			if ( (msg1->m_nMultiRate == 0) && (msg1->lRate != 0) )
				rate = msg1->lRate;
			else
				rate = msg1->m_nMultiRate;
						
			s += " [";
			s += CUtils::GetTransferString(rate);
			s += "]";
		}

		if ( g_pConfig->GetTransferViewOptions(etvoELAPSEDTIMEMULTI) )
		{
			ulonglong rate,r;

			rate = msg1->lSize-msg1->lSizeDone;

			if ( (msg1->m_nMultiRate == 0) && (msg1->lRate != 0) )
				r=msg1->lRate;
			else
				r=msg1->m_nMultiRate;
			
			if ( r>0 )
				rate/=r;

			s += " [";
			s += CUtils::GetTimeString(rate);
			s += "]";
		}

		TransferListItem->pItem->setText(2,s.Data());
	}

	pViewTransferList->UnLock();
}

/** */
bool DCTransferView::UpdateTransferWaitList( CMessageDMFileObject * msg )
{
	CStringList * StringList1=0, *StringList2=0;
	DCTransferQueueItem * TransferQueueItem1=0,* TransferQueueItem2=0;
	CString sLocalFileName;
	QString s;
	bool bLVWaitUpdate = FALSE;

	pQueueList->Lock();

	// get the list for the nick
	if ( pQueueList->Get( msg->m_sNick, (CObject *&) StringList1) != 0 )
	{
		// not found
		if ( msg->m_bRemoveFile == TRUE )
		{
			// abort
			pQueueList->UnLock();
			return bLVWaitUpdate;
		}
		else
		{
			// create new list for this nick
			StringList1 = new CStringList();
			pQueueList->Add( msg->m_sNick, StringList1 );
		}
	}

	// get the list for the hub
	if ( StringList1->Get( msg->m_sHubName, (CObject *&) TransferQueueItem1 ) != 0 )
	{
		// create new list
		ListView_TRANSFERWAIT->setUpdatesEnabled(FALSE);
		bLVWaitUpdate = TRUE;

		TransferQueueItem1 = new DCTransferQueueItem();
		TransferQueueItem1->pObject = new CStringList();
		TransferQueueItem1->pItem   = new Q3ListViewItem( ListView_TRANSFERWAIT, msg->m_sNick.Data() );
		TransferQueueItem1->pItem->setText(1,msg->m_sHubName.Data());
		TransferQueueItem1->pItem->setText(2,msg->m_sHubHost.Data());

		TransferQueueItem1->sHubName = msg->m_sHubName;
		TransferQueueItem1->sHubHost = msg->m_sHubHost;

		StringList1->Add( msg->m_sHubName, TransferQueueItem1 );
	}
	else
	{
		// update the view
		if ( TransferQueueItem1->sHubHost != msg->m_sHubHost )
		{
			ListView_TRANSFERWAIT->setUpdatesEnabled(FALSE);
			bLVWaitUpdate = TRUE;
			TransferQueueItem1->sHubHost = msg->m_sHubHost;
			TransferQueueItem1->pItem->setText(2,msg->m_sHubHost.Data());
		}
	}

	// get the list with the files
	StringList2 = (CStringList*)TransferQueueItem1->pObject;

	TransferQueueItem2 = 0;

	// get the fileobject from the file list
	if ( msg->m_sRemoteFile != "" )
	{
		StringList2->Get( msg->m_sRemoteFile, (CObject *&) TransferQueueItem2 );
	}

	// check for remove this entry
	if ( msg->m_bRemoveFile == TRUE )
	{
		ListView_TRANSFERWAIT->setUpdatesEnabled(FALSE);
		bLVWaitUpdate = TRUE;

		// remove all files with the root
		if ( msg->m_sRemoteFile == "" )
		{
			// remove all items from the list and view
			TransferQueueItem2 = 0;

			while ( StringList2->Next( (CObject *&) TransferQueueItem2 ) )
			{
				TransferQueueItem1->pItem->takeItem(TransferQueueItem2->pItem);
				delete TransferQueueItem2->pItem;
				TransferQueueItem2->pItem = 0;
				delete (CMessageDMFileObject*)TransferQueueItem2->pObject;
				TransferQueueItem2->pObject = 0;
			}

			// clear the list
			StringList2->Clear();

			// remove the root
			ListView_TRANSFERWAIT->takeItem(TransferQueueItem1->pItem);
			delete TransferQueueItem1->pItem;
			TransferQueueItem1->pItem = 0;
			delete (CStringList*)TransferQueueItem1->pObject;
			TransferQueueItem1->pObject = 0;

			StringList1->Del( msg->m_sHubName );

			if ( StringList1->Count() == 0 )
			{
				pQueueList->Del( msg->m_sNick );
			}
		}
		// remove only the given file
		else
		{
			// remove the file
			if ( TransferQueueItem2 != 0 )
			{
				TransferQueueItem1->pItem->takeItem(TransferQueueItem2->pItem);
				delete TransferQueueItem2->pItem;
				TransferQueueItem2->pItem = 0;
				delete (CMessageDMFileObject*)TransferQueueItem2->pObject;
				StringList2->Remove( msg->m_sRemoteFile );
				delete TransferQueueItem2;
				TransferQueueItem2 = 0;
			}

			// remove empty list ...
			if ( StringList2->Count() == 0 )
			{
				ListView_TRANSFERWAIT->takeItem(TransferQueueItem1->pItem);
				delete TransferQueueItem1->pItem;
				TransferQueueItem1->pItem = 0;
				delete (CStringList*)TransferQueueItem1->pObject;
				TransferQueueItem1->pObject = 0;
				StringList1->Del( msg->m_sHubName );

				if ( StringList1->Count() == 0 )
				{
					pQueueList->Del( msg->m_sNick );
				}
			}
		}
	}
	// update the entry
	else
	{
		// set the user state
		switch(msg->m_eTransferWaitState)
		{
			case etwsWAIT:
				s = tr("Wait");
				break;
			case etwsIDLE:
				s = tr("Idle");
				break;
			case etwsRUN:
				s = tr("Run");
				s += " ["+QString().setNum(msg->m_nConnections)+"]";
				break;
			case etwsHUBOFFLINE:
				s = tr("Hub offline");
				break;
			case etwsUSEROFFLINE:
				s = tr("User offline");
				break;
			case etwsUSERBUSY:
				s = tr("User busy");
				break;
			case etwsSENDERROR:
				s = tr("Send error");
				break;
			default:
				s = tr("Unknown");
				break;
		}

		TransferQueueItem1->pItem->setText(3,s);

		if ( msg->m_sRemoteFile != "" )
		{
			// create a entry for this file
			if ( TransferQueueItem2 == 0 )
			{
				ListView_TRANSFERWAIT->setUpdatesEnabled(FALSE);
				bLVWaitUpdate = TRUE;

				TransferQueueItem2 = new DCTransferQueueItem();
			
				// clear object pointer
				TransferQueueItem2->pObject = new CMessageDMFileObject();
				*(CMessageDMFileObject*)TransferQueueItem2->pObject = *msg;
				TransferQueueItem2->pItem   = new Q3ListViewItem ( TransferQueueItem1->pItem, "" );
				TransferQueueItem2->pItem->setText(1, msg->m_sRemoteFile.Data());
				TransferQueueItem2->pItem->setText(2, CString().setNum(msg->m_nSize).Data());

				StringList2->Add( msg->m_sRemoteFile, TransferQueueItem2 );
			}

			// update the file state
			switch(msg->m_eTransferFileState)
			{
				case etfsNONE:
					s = tr("Idle");
					break;
				case etfsTRANSFER:
					s = tr("Transfer");
					break;
				case etfsERROR:
					s = tr("Error");
					break;
				case etfsPAUSE:
					s = tr("Pause");
					break;
				default:
					s = tr("Unknown");
					break;
			}

			if ( msg->m_bMulti == TRUE )
			{
				s = "*"+s;
			}

			s += "/"+QString().setNum(msg->m_nPriority);

			TransferQueueItem2->pItem->setText(3,s);
		}
	}

	pQueueList->UnLock();

	return bLVWaitUpdate;
}

/** */
bool DCTransferView::UpdateLocalFileList( CMessageDMFileObject * msg )
{
	CStringList * StringList1=0, *StringList2=0;
	DCTransferQueueItem * TransferQueueItem1=0,* TransferQueueItem2=0;
	QString s;
	bool bLVWaitUpdate = FALSE;
	CString hnindex="";

	pQueueLocalList->Lock();

	if ( msg->m_sLocalFile == "" )
	{
		if  ( msg->m_bRemoveFile == FALSE )
		{
			// abort
			pQueueLocalList->UnLock();
			return bLVWaitUpdate;
		}
		else
		{
			// This is a bad case : when removing all downloads corresponding to a nick

			// get the list for the nick
			if ( pQueueList->Get( msg->m_sNick, (CObject *&) StringList1) != 0 )
			{
				printf("Nick not found while updating LocalFileList\n");
				pQueueLocalList->UnLock();
				return bLVWaitUpdate;
			}

			// get the list for the hub
			if ( StringList1->Get( msg->m_sHubName, (CObject *&) TransferQueueItem1 ) != 0 )
			{
				printf("Hub not found while updating LocalFileList\n");
				pQueueLocalList->UnLock();
				return bLVWaitUpdate;
			}

			// get the list with the files
			StringList2 = (CStringList*)TransferQueueItem1->pObject;

			// remove all items from the list
			TransferQueueItem2 = 0;
			while ( StringList2->Next( (CObject *&) TransferQueueItem2 ) )
			{
				DCTransferQueueItem * TransferQueueItem3=0, * TransferQueueItem4=0;
				CMessageDMFileObject * msg2;

				msg2 = (CMessageDMFileObject *) (TransferQueueItem2->pObject);
				hnindex = msg2->m_sHubName + "|" + msg2->m_sNick;

				if ( pQueueLocalList->Get( msg2->m_sLocalFile, (CObject *&) TransferQueueItem3) == 0 )
				{
					StringList1 = (CStringList*)TransferQueueItem3->pObject;
					if ( StringList1->Get( hnindex, (CObject *&) TransferQueueItem4 ) == 0 )
					{
						bLVWaitUpdate = TRUE;
						TransferQueueItem3->pItem->takeItem(TransferQueueItem4->pItem);
						delete TransferQueueItem4->pItem;
						StringList1->Del(hnindex);

						if ( StringList1->Count() == 0 )
						{
							ListView_LOCALFILES->takeItem(TransferQueueItem3->pItem);
							delete TransferQueueItem3->pItem;
							delete StringList1;
							pQueueLocalList->Del(msg2->m_sLocalFile);
						}
					}
				}
			}
			pQueueLocalList->UnLock();
			return bLVWaitUpdate;
		}
	}

	if ( pQueueLocalList->Get( msg->m_sLocalFile, (CObject *&) TransferQueueItem1) != 0 )
	{
		// not found
		if ( msg->m_bRemoveFile == TRUE )
		{
			// abort
			pQueueLocalList->UnLock();
			return bLVWaitUpdate;
		}
		else
		{
			QString size_h;

			// create new list for this nick
			TransferQueueItem1 = new DCTransferQueueItem();
			StringList1 = new CStringList();
			TransferQueueItem1->pObject = StringList1;

			size_h = QString(CString().setNum(msg->m_nSize).Data());
			size_h += " (";
			size_h.append(CUtils::GetSizeString(msg->m_nSize,g_pConfig->GetUnit()).Data());
			size_h += ")";

			TransferQueueItem1->pItem = new DC_QListViewItem( ListView_LOCALFILES );
			((DC_QListViewItem*)TransferQueueItem1->pItem)->mycol   = 1;
			((DC_QListViewItem*)TransferQueueItem1->pItem)->myvalue = msg->m_nSize;
			TransferQueueItem1->pItem->setText(0,msg->m_sLocalFile.Data());
			TransferQueueItem1->pItem->setText(1,size_h);

			pQueueLocalList->Add( msg->m_sLocalFile, TransferQueueItem1 );
		}
	}

	StringList1 = (CStringList*)TransferQueueItem1->pObject;

	hnindex = msg->m_sHubName + "|" + msg->m_sNick;

	// check for remove this entry
	if ( msg->m_bRemoveFile == TRUE )
	{
		if ( StringList1->Get( hnindex, (CObject *&) TransferQueueItem2 ) == 0 )
		{
			TransferQueueItem1->pItem->takeItem(TransferQueueItem2->pItem);
			delete TransferQueueItem2->pItem;
			StringList1->Del(hnindex);

			if ( StringList1->Count() == 0 )
			{
				ListView_LOCALFILES->takeItem(TransferQueueItem1->pItem);
				delete TransferQueueItem1->pItem;
				delete StringList1;
				pQueueLocalList->Del(msg->m_sLocalFile);
			}
		}
	}
	else
	{
		if ( StringList1->Get( hnindex, (CObject *&) TransferQueueItem2 ) != 0 )
		{
			TransferQueueItem2 = new DCTransferQueueItem();

			TransferQueueItem2->pItem = new DC_QListViewItem( TransferQueueItem1->pItem );
			TransferQueueItem2->pItem->setText(0,msg->m_sNick.Data());
			TransferQueueItem2->pItem->setText(1,msg->m_sHubName.Data());
			TransferQueueItem2->pItem->setText(2,msg->m_sRemoteFile.Data());
			// set the user state
			switch(msg->m_eTransferWaitState)
			{
				case etwsWAIT:
					s = tr("Wait");
					break;
				case etwsIDLE:
					s = tr("Idle");
					break;
				case etwsRUN:
					s = tr("Run");
					s += " ["+QString().setNum(msg->m_nConnections)+"]";
					break;
				case etwsHUBOFFLINE:
					s = tr("Hub offline");
					break;
				case etwsUSEROFFLINE:
					s = tr("User offline");
					break;
				case etwsUSERBUSY:
					s = tr("User busy");
					break;
				case etwsSENDERROR:
					s = tr("Send error");
					break;
				default:
					s = tr("Unknown");
					break;
			}

			TransferQueueItem2->pItem->setText(3,s);

			StringList1->Add( hnindex, TransferQueueItem2 );
		}
	}

	pQueueLocalList->UnLock();

	return TRUE;
}

/** */
void DCTransferView::NewLocalFileBrowser( bool lock )
{
	DCFileBrowser *bft;

	QDialog *d = new QDialog(this);
	QGridLayout *Layout = new QGridLayout( d, 1, 1, 4, 4, "Layout"); 
	
	if ( !lock )
	{
		bft = new DCFileBrowser( pMdiArea, "Filebrowser", 0, TRUE );
		bft->setAttribute(Qt::WA_DeleteOnClose);
	}
	else
	{
		bft = new DCFileBrowser( d, "Filebrowser", 0, TRUE );
	}
	
	Layout->addWidget( bft, 0, 0 );
	// set transfer
	d->setCaption( tr("My") + " - Filebrowser" );
	bft->InitTree(g_pConfig->GetNick().Data(),"","","/dev/null/ownfilelist");
	bft->layout()->setSpacing(0);
	bft->layout()->setMargin(0);
	
	if ( !lock )
	{
		bft->installEventFilter(this);
		pFileList->Add(bft);
		bft->show();
	}
	else
	{
		d->exec();
		delete d;
	}
}

/** */
void DCTransferView::NewFileBrowser( QString nick, QString hubname, QString hubhost, QString filename )
{
	DCFileBrowser *bft;
	bft = new DCFileBrowser( pMdiArea, "Filebrowser" );
	bft->setAttribute(Qt::WA_DeleteOnClose);

	// set transfer
	bft->installEventFilter(this);
	bft->InitTree(nick,hubname,hubhost,filename);
	pFileList->Add(bft);
	bft->show();
}

bool DCTransferView::IsUserInQueue( QString Nick, QString Hubname )
{
	CStringList * StringList1=0;
	DCTransferQueueItem * TransferQueueItem1=0;

	pQueueList->Lock();

	// get the list corresponding to the nick
	if ( pQueueList->Get( Nick.toAscii().data(), (CObject *&) StringList1) != 0 )
	{
		pQueueList->UnLock();
		return FALSE;
	}

	// search for the corresponding hub
	if ( StringList1->Get( Hubname.toAscii().data(), (CObject *&) TransferQueueItem1 ) != 0 )
	{
		pQueueList->UnLock();
		return FALSE;
	}

	pQueueList->UnLock();
	return TRUE;
}

/** */
void DCTransferView::GetLocalFilesList( QStringVector & LocalFiles, ulonglong size )
{
	Q3ListViewItem * LocalFileItem=0;

	LocalFiles.clear();

	LocalFileItem = ListView_LOCALFILES->firstChild();

	while( LocalFileItem )
	{
		if ( LocalFileItem->text(1) != "0" ) // size
		{
			if (( size == 0 ) || ( ((DC_QListViewItem*)LocalFileItem)->myvalue == size ))
			{
				LocalFiles.push_back( LocalFileItem->text(0) );
			}
		}
		LocalFileItem = LocalFileItem->nextSibling();
	}

	/*
	// Alternative method:
	// Trying not to use QListViewItem should be faster
	CString localfile;
	CStringList * StringList1=0;
	DCTransferQueueItem * TransferQueueItem;

	pQueueLocalList->Lock();

	while ( pQueueLocalList->Next( localfile, (CObject *&) TransferQueueItem) != 0 )
	{
		printf("\nLocalFile: %s\n\n", localfile.Data());
		StringList1 = (CStringList*) TransferQueueItem->pObject;
		TransferQueueItem = 0;
		if ( StringList1->Next( (CObject *&) TransferQueueItem) != 0 )
		{
			int localsize=???;
			if ( localsize != 0 )
			{
				printf("\nSize: %lu\n\n", localsize);
				if (( size == 0 ) || ( localsize == size ))
				{
					QString Qlocalfile( localfile.Data() );
					if ( Qlocalfile.contains('\\') )
						Qlocalfile = Qlocalfile.section('\\',-1);
					else
						Qlocalfile = Qlocalfile.section('/',-1);
					LocalFiles.push_back( Qlocalfile );
				}
			}
		}
	}

	pQueueLocalList->UnLock();
	*/
}

/** */
ulonglong DCTransferView::FindTransferID( Q3ListViewItem * item )
{
	CMessageDMTransferObject * msg;
	DCTransferListItem * TransferListItem = 0;
	ulonglong id = 0;

	pViewTransferList->Lock();

	while ( pViewTransferList->Next( (CObject*&)TransferListItem ) )
	{
		msg = (CMessageDMTransferObject *) TransferListItem->pObject;

		if ( TransferListItem->pItem == item )
		{
			id = msg->m_nTransferID;
			break;
		}
	}

	pViewTransferList->UnLock();

	return id;
}

/** */
bool DCTransferView::GetTransferMessageObject( Q3ListViewItem * item, CMessageDMTransferObject * obj )
{
	bool res = FALSE;
	
	CMessageDMTransferObject * msg;
	DCTransferListItem * TransferListItem = 0;

	pViewTransferList->Lock();

	while ( pViewTransferList->Next( (CObject*&)TransferListItem ) )
	{
		msg = (CMessageDMTransferObject *) TransferListItem->pObject;

		if ( TransferListItem->pItem == item )
		{
			*obj = *msg;
			res = TRUE;
			break;
		}
	}

	pViewTransferList->UnLock();

	return res;
}

/** */
eConnectionState DCTransferView::GetTransferDirection( ulonglong sid )
{
	CMessageDMTransferObject * msg;
	DCTransferListItem * TransferListItem = 0;
	eConnectionState state = estNONE;

	pViewTransferList->Lock();

	if ( pViewTransferList->Get( CString().setNum(sid), (CObject*&)TransferListItem ) == 0 )
	{
		msg = (CMessageDMTransferObject *) TransferListItem->pObject;
		if ( msg )
			state = msg->eState;
	}

	pViewTransferList->UnLock();

	return state;
}

/** */
void DCTransferView::ConnectToAllHubs()
{
	CStringList * StringList1=0;
	DCTransferQueueItem * TransferQueueItem1=0;

	pQueueList->Lock();

	while ( pQueueList->Next( (CObject *&) StringList1) )
	{
		TransferQueueItem1 = 0;

		while ( StringList1->Next( (CObject *&) TransferQueueItem1 ) )
		{
			g_pConnectionManager->Connect( TransferQueueItem1->sHubName.Data(), TransferQueueItem1->sHubHost.Data() );
		}
	}

	pQueueList->UnLock();
}

/** */
void DCTransferView::SearchFileClone(QString filename, ulonglong size)
{
	QString searchtxt;
	QRegExp re_ext;

	// convert local file name into a suitable search expression
	if ( filename.contains('\\') )
		searchtxt = filename.section('\\',-1);
	else
		searchtxt = filename.section('/',-1);
	searchtxt.replace(QRegExp("_")," ");
	searchtxt.replace(QRegExp("-")," ");
	re_ext = QRegExp("\\.(\\w{3,4})$");
	re_ext.search( searchtxt );
	searchtxt.replace( re_ext, " "+re_ext.cap(1) );
	re_ext = QRegExp(",");
	while (searchtxt.contains(re_ext))
	    searchtxt.replace(re_ext," ");
	re_ext = QRegExp("\\s(a|the|and|or|in|to|of)\\s");
	re_ext.setCaseSensitive(false);
	while (searchtxt.contains(re_ext))
	    searchtxt.replace(re_ext," ");
	re_ext = QRegExp("^(the|a)\\s");
	re_ext.setCaseSensitive(false);
	while (searchtxt.contains(re_ext))
	    searchtxt.replace(re_ext,"");
	re_ext = QRegExp("\\s{2,}");
	while (searchtxt.contains(re_ext))
	    searchtxt.replace(re_ext," ");

	g_pHubSearch->Combobox_SEARCH->setEditText(searchtxt);
	g_pHubSearch->LineEdit_SEARCHSIZE->setText(CString().setNum(size).Data());
	g_pHubSearch->ComboBox_SEARCHTYPE->setCurrentItem(1);
	g_pHubSearch->ComboBox_SEARCHUNIT->setCurrentItem(0);
	g_pHubSearch->ComboBox_SEARCHLIMIT->setCurrentItem(2);

	if ( g_pHubSearch->isMinimized() )
	{
		g_pHubSearch->showNormal();
	}
	else if ( g_pHubSearch->isVisible()==FALSE )
	{
		g_pHubSearch->setEnabled(TRUE);
		g_pHubSearch->show();
	}

	if ( g_pHubSearch->TabWidget_HUBSEARCH->isVisible()==FALSE )
	{
		g_pHubSearch->TabWidget_HUBSEARCH->show();
	}
}

/** */
void DCTransferView::EditExistingTransfer(QString & nick, QString & hubname, QString & hubhost, CList<DCHubObject> * list )
{
	DCEditTransfer * dialg;

	dialg = new DCEditTransfer();

	dialg->Init(nick,hubname,hubhost,list);

	if ( dialg->exec() == QDialog::Accepted )
	{
		CString OldNick;
		CString OldHubname;

		OldNick = nick.toAscii().data();
		OldHubname = hubname.toAscii().data();

		nick	= dialg->LineEdit_NICK->text();
		hubname	= dialg->LineEdit_HUBNAME->text();
		hubhost	= dialg->LineEdit_HUBHOST->text();

		DLM_QueueEdit( OldNick, OldHubname, nick.toAscii().data(), hubname.toAscii().data(), hubhost.toAscii().data());
	}

	delete dialg;
}

/** */
int DCTransferView::selectedItems( Q3ListView * list, QList<Q3ListViewItem*> & lst )
{
	Q3ListViewItemIterator it( (Q3ListView *)list );

	for ( ; it.current(); it++ )
	{
		if ( it.current()->isSelected() )
		{
			lst.append(it.current());
		}
	}

	return lst.count();
}

/** */
void DCTransferView::slotRightButtonClickedTransferList( Q3ListViewItem * item , const QPoint &, int )
{
	QAction * chosen = 0;
	QMenu * m;
	DCMenuHandler mhandler;
	CMessageDMTransferObject transfermsg;
	
	if( item == 0 )
	{
		return;
	}

	if ( GetTransferMessageObject(item,&transfermsg) == FALSE )
	{
		return;
	}

	m = new QMenu(this);

	QAction * privchat = mhandler.addAction( m, emiPRIVATE_CHAT, (transfermsg.m_sDstNick!="") );
	QAction * browse = mhandler.addAction( m, emiBROWSE_USER_FILES, (transfermsg.m_sDstNick!="") ); // ,(UserFileInfo.sUserFileList != "") );
	mhandler.addAction( m, emiSEPARATOR );
	QAction * close = mhandler.addAction( m, emiCLOSE_TRANSFER );
	QAction * rate = mhandler.addAction( m, emiCHANGE_TRANSFER_RATE, (GetTransferDirection(transfermsg.m_nTransferID) == estTRANSFERUPLOAD) && (g_pConfig->GetDynamicUploadRate() == FALSE));

	chosen = m->exec(QCursor::pos());

	delete m;

	if ( chosen == privchat )
        {
                // open chat with user
                g_pConnectionManager->OpenPrivateChat( transfermsg.sHubName.Data(), transfermsg.m_sHubHost.Data(), transfermsg.m_sDstNick.Data() );
        }
        else if ( chosen == browse )
        {
		// TODO: check if hub online ...

                // add transfer to the waitlist
                DLM_QueueAdd( transfermsg.m_sDstNick, transfermsg.sHubName,
                              transfermsg.m_sHubHost,
                              DC_USER_FILELIST_HE3, DC_USER_FILELIST_HE3, "", "", eltBUFFER,
                              0, 0, 0, "" );
        }
	else if ( chosen == close )
	{
		if ( DLM_TransferClose( transfermsg.m_nTransferID ) == FALSE )
		{
			// TODO: error message
		}
	}
	else if ( chosen == rate )
	{
		bool ok = FALSE;
		ulonglong rate;

		if ( DLM_TransferGetRate( transfermsg.m_nTransferID, rate ) == FALSE )
		{
			// TODO: error message
		}
		else
		{
			rate = QInputDialog::getInteger(
				tr("Change Transfer-Rate"),
				tr("Please enter a Transfer-Rate [B/s] (0=off)"), rate, 0, 9999999, 512, &ok, this );
		}

		if ( ok )
		{
			if ( (rate < 512) && (rate != 0) )
			{
				rate = 512;
			}

			if ( DLM_TransferSetRate( transfermsg.m_nTransferID, rate ) == FALSE )
			{
				// TODO: error message
			}
		}
	}
}

/** */
void DCTransferView::slotRightButtonClickedTransferWaitList( Q3ListViewItem * /*item*/ , const QPoint &, int )
{
        QAction * chosen = 0;
        QMenu * m;
	DCMenuHandler mhandler;
        Q3ListViewItem * item1;
        QString nick,hubname,hubhost,file;
        CUserFileInfo UserFileInfo;
        QList<Q3ListViewItem*> selitems;
        Q3ListViewItem * curitem;
        bool inactiveTransfer = TRUE, b;
	int numSelected;

	numSelected = selectedItems( ListView_TRANSFERWAIT, selitems );

	if ( numSelected == 0 )
	{
		return;
	}

	for ( int i = 0; i < selitems.size(); i++ )
        {
		curitem = selitems.at(i);
		
                if ( curitem->depth() == 1 )
                {
                        item1 = curitem->parent();
                }
                else
                {
                        item1 = curitem;
                }

                if ( item1 == 0 )
                {
                        return;
                }

                nick    = item1->text(0);
                hubname = item1->text(1);
                hubhost = item1->text(2);

		if ( item1 != curitem )
		{
			file = curitem->text(1);
		}
		else
		{
			file = "";
		}

		if ( DLM_QueueGetFileInfo(nick.toAscii().data(),hubname.toAscii().data(),hubhost.toAscii().data(),file.toAscii().data(),&UserFileInfo) == FALSE )
		{
			return;
		}

		inactiveTransfer = inactiveTransfer && ( ((UserFileInfo.eWaitState != etwsRUN) && (UserFileInfo.eWaitState != etwsWAIT)) ||
					( (file != "") && (UserFileInfo.eFileState!=etfsTRANSFER)));
        }

        if ( numSelected != 1 )
        {
		nick = hubname = hubhost = "";
        }

	m = new QMenu(this);

	QAction * pause = mhandler.addAction( m, emiPAUSE_TRANSFER_QUEUE );
	QAction * resume = mhandler.addAction( m, emiRESUME_TRANSFER_QUEUE );
	QAction * remove = mhandler.addAction( m, emiREMOVE_TRANSFER_QUEUE, inactiveTransfer );
	//DCMenuHandler::InsertMenu( m, emiREMOVE_TRANSFER_QUEUE_DISK, (inactiveTransfer && FALSE) ); //(TransferItem.eState == etwsIDLE) );
	mhandler.addAction( m, emiSEPARATOR );
	QAction * tryconn = mhandler.addAction( m, emiTRY_CONNECT, (inactiveTransfer) );
	QAction * connhub = mhandler.addAction( m, emiCONNECT_TO_HUB );
	QAction * connallhub = mhandler.addAction( m, emiCONNECT_TO_ALL_HUBS );
	QAction * browse = mhandler.addAction( m, emiBROWSE_USER_FILES, (numSelected==1) );
	mhandler.addAction( m, emiSEPARATOR );
	QAction * fileinfo = mhandler.addAction( m, emiFILE_INFO, ((UserFileInfo.sLocalFile != "") && (numSelected==1)) );
	mhandler.addAction( m, emiSEPARATOR );
	QAction * edit = mhandler.addAction( m, emiEDIT_TRANSFER, ((selitems.first()->depth() == 0) && (inactiveTransfer) && (numSelected==1)) );
	QAction * editprio = mhandler.addAction( m, emiEDIT_FILE_PRIORITY );
	QAction * updserver = mhandler.addAction( m, emiUPDATE_SERVER);
	QAction * save = mhandler.addAction( m, emiSAVE_QUEUE );

        chosen = m->exec(QCursor::pos());
        delete m;

        if ( chosen == connhub )
        {
                for ( int i = 0; i < selitems.size(); i++ )
                {
			curitem = selitems.at(i);
			
                        if ( curitem->depth() == 1 )
                        {
                                item1 = curitem->parent();
                        }
                        else
                        {
                                item1 = curitem;
                        }
                        hubname = item1->text(1);
                        hubhost	= item1->text(2);

			if ( g_pConnectionManager->IsHubOnline(hubname.toAscii().data(),hubhost.toAscii().data()) == ehsNONE )
			{
				g_pConnectionManager->Connect( hubname.toAscii().data(), hubhost.toAscii().data() );
			}
		}
        }
        else if ( chosen == connallhub )
        {
                ConnectToAllHubs();
        }
        else if ( chosen == browse )
        {
                NewFileBrowser(nick,hubname,hubhost,UserFileInfo.sLocalFile.Data());
        }
        else if ( chosen == tryconn )
        {
			for ( int i = 0; i < selitems.size(); i++ ) {
				curitem = selitems.at(i);
				if ( curitem->depth() == 1 ) {
					item1 = curitem->parent();
				} else {
					item1 = curitem;
				}
				nick    = item1->text(0);
				hubname = item1->text(1);
                if ( DLM_TransferConnect( nick.toAscii().data(), hubname.toAscii().data() ) == FALSE ) {
					// error message
					QMessageBox::critical( 0, tr("Try Connect"),
						tr("User and Hub not found in the queue !") + "\n\n" +
						tr("Nick:") + " '" +
						nick + "'\n" +
						tr("Hub:") + " '" + hubname + "'\n" );
				}
			}
        }
	else if ( (chosen == pause) || (chosen == resume) )
	{
		if ( chosen == pause )
		{
			b = TRUE;
		}
		else
		{
			b = FALSE;
		}

                for ( int i = 0; i < selitems.size(); i++ )
                {	
			curitem = selitems.at(i);
			
                        if ( curitem->depth() == 1 )
                        {
                                item1 = curitem->parent();
                        }
                        else
                        {
                                item1 = curitem;
                        }

                        nick    = item1->text(0);
                        hubname = item1->text(1);

                        if ( item1 != curitem )
                        {
                                file = curitem->text(1);
                        }
                        else
                        {
                                file = "";
                        }

                        if ( DLM_QueuePause( nick.toAscii().data(), hubname.toAscii().data(), file.toAscii().data(), b ) == FALSE )
                        {
                                // TODO: error handling
                        }
                }
	}
        else if ( chosen == remove )
        {
		if (g_pConfig->GetQueryOnFileDelete()) {
			// first we ask the user
			switch( QMessageBox::warning( this, tr("Remove Transfer"),
				tr("You are sure ?"),
				tr("Remove"),
				tr("Cancel"), 0, 0, 1 ) )
			{
				case 1: // The user clicked the Quit or pressed Escape
					return;
				default:
					break;
			}
		}

                for ( int i = 0; i < selitems.size(); i++ )
                {
			curitem = selitems.at(i);
			
                        if ( curitem->depth() == 1 )
                        {
                                item1 = curitem->parent();
                        }
                        else
                        {
                                item1 = curitem;
                        }

                        nick    = item1->text(0);
                        hubname = item1->text(1);

                        if ( item1 != curitem )
                        {
                                file = curitem->text(1);
                        }
                        else
                        {
                                file = "";
                        }

                        if ( DLM_QueueRemove(nick.toAscii().data(),hubname.toAscii().data(),file.toAscii().data()) == FALSE )
                        {
                                // TODO: error handling
                        }
                }
        }
        else if ( chosen == fileinfo )
        {
		DCFileTransferInfo * ft;

		ft = new DCFileTransferInfo(UserFileInfo.sLocalFile);
		ft->exec();
		delete ft;
        }
        else if ( chosen == updserver )
        {
                for ( int i = 0; i < selitems.size(); i++ )
                {
			curitem = selitems.at(i);
			
                        if ( curitem->depth() == 1 )
                        {
                                item1 = curitem->parent();
                        }
                        else
                        {
                                item1 = curitem;
                        }

                        nick    = item1->text(0);
                        hubname = item1->text(1);

			if ( DLM_QueueUpdateHub( nick.toAscii().data(), hubname.toAscii().data() ) == FALSE )
			{
				// TODO: error message ...
			}
		}
        }
        else if ( chosen == edit )
        {
		CList<DCHubObject> list;

		curitem = selitems.first();

                nick    = curitem->text(0);
                hubname = curitem->text(1);
                hubhost = curitem->text(2);

		DLM_QueueGetHub( nick.toAscii().data(), hubname.toAscii().data(), &list );

                EditExistingTransfer( nick, hubname, hubhost, &list );
        }
	else if ( chosen == editprio )
	{
		bool ok = FALSE;
		int priority=0;

		priority = QInputDialog::getInteger(
			tr("Change File-Priority"),
			tr("Please enter a priority"), priority, 0, MAX_FILE_PRIORITY, 1, &ok, this );

		if ( ok )
		{
	                for ( int i = 0; i < selitems.size(); i++ )
        	        {
				curitem = selitems.at(i);
				
	                        if ( curitem->depth() == 0 )
        	                {
			                for ( item1 = curitem->firstChild(); item1; item1 = item1->nextSibling() )
        			        {
			                        nick    = curitem->text(0);
        			                hubname = curitem->text(1);
						file    = item1->text(1);

						if ( DLM_QueueSetFilePriority( nick.toAscii().data(), hubname.toAscii().data(), file.toAscii().data(), priority ) == FALSE )
						{
							// TODO: error message ...
						}
					}
				}
	                        else if ( curitem->depth() == 1 )
        	                {
                	                item1 = curitem->parent();

		                        nick    = item1->text(0);
        		                hubname = item1->text(1);
					file    = curitem->text(1);

					if ( DLM_QueueSetFilePriority( nick.toAscii().data(), hubname.toAscii().data(), file.toAscii().data(), priority ) == FALSE )
					{
						// TODO: error message ...
					}
				}
			}
		}
	}
        else if ( chosen == save )
        {
                DLM_SaveQueue();
        }

	selitems.clear();
}


/** */
void DCTransferView::slotRightButtonClickedLocalFilesList( Q3ListViewItem * item , const QPoint &, int )
{
	QAction * chosen = 0;
	QMenu * m;
	DCMenuHandler mhandler;
	Q3ListViewItem * item1;
	QString localfile,nick,hubname,remotefile;
	ulonglong size;
	CUserFileInfo UserFileInfo;
	bool removetransfer = true;
	DCFileChunkObject * pFileChunk;
	bool fileHasTTH = false;

	if( item == 0 )
	{
		return;
	}

	if ( item->depth() == 1 )
	{
		item1 = item->parent();
	}
	else
	{
		item1 = item;
	}

	if ( item1 == 0 )
	{
		return;
	}

	localfile = item1->text(0);
	size      = CString(item1->text(1).toAscii().data()).asULL();

	if ( item->depth() == 1 )
	{
		nick       = item->text(0);
		hubname    = item->text(1);
		remotefile = item->text(2);

		if (DLM_QueueGetFileInfo(nick.toAscii().data(),hubname.toAscii().data(),"hubhost",remotefile.toAscii().data(),&UserFileInfo) == false)
	        {
			return;
		}
		removetransfer = ((UserFileInfo.eWaitState != etwsRUN) && (UserFileInfo.eWaitState != etwsWAIT)) ||
                                   ( (remotefile != "") && (UserFileInfo.eFileState!=etfsTRANSFER));
	}
	else
	{
		Q3ListViewItem * tmpitem;
		for(tmpitem=item->firstChild(); tmpitem; tmpitem=tmpitem->nextSibling())
                {
			nick       = tmpitem->text(0);
			hubname    = tmpitem->text(1);
			remotefile = tmpitem->text(2);
			if (DLM_QueueGetFileInfo(nick.toAscii().data(),hubname.toAscii().data(),"hubhost",remotefile.toAscii().data(),&UserFileInfo) == false)
			{
				return;
			}
			removetransfer = removetransfer && ( ((UserFileInfo.eWaitState != etwsRUN) && (UserFileInfo.eWaitState != etwsWAIT)) ||
							     ( (remotefile != "") && (UserFileInfo.eFileState!=etfsTRANSFER)));
		}

		nick       = "";
		hubname    = "";
		remotefile = "";
	}

	// check if the file has a TTH
	pFileChunk = DLM_QueueGetFileChunk(localfile.toAscii().data());
	if ( pFileChunk != 0 )
	{
		if ( pFileChunk->m_sHash != "")
		{
			fileHasTTH = true;
		}
	}

	m = new QMenu(this);

	QAction * clone = mhandler.addAction( m, emiSEARCH_FILE_CLONE, (size > 0) );
	QAction * clonetth = mhandler.addAction( m, emiSEARCH_FILE_CLONE_TTH, fileHasTTH );
	mhandler.addAction( m, emiSEPARATOR );
	QAction * remove = mhandler.addAction( m, emiREMOVE_TRANSFER_QUEUE, removetransfer );
	//DCMenuHandler::InsertMenu( m, emiREMOVE_TRANSFER_QUEUE_DISK, (removetransfer && FALSE) ); //(TransferItem.eState == etwsIDLE) );
	mhandler.addAction( m, emiSEPARATOR );

	QAction * info = mhandler.addAction( m, emiFILE_INFO, (localfile != "") && (size > 0) );

	chosen = m->exec(QCursor::pos());

	delete m;

        if ( chosen == remove )
        {
		if (g_pConfig->GetQueryOnFileDelete()) {
			// first we ask the user
			switch( QMessageBox::warning( this, tr("Remove Transfer"),
				tr("You are sure ?"),
				tr("Remove"),
				tr("Cancel"), 0, 0, 1 ) )
			{
				case 1: // The user clicked the Quit or pressed Escape
					return;
				default:
					break;
			}
		}

                if (item->depth() == 0)
                {
                        Q3ListViewItem * tmpitem;
                        for(tmpitem=item->firstChild(); tmpitem; tmpitem=tmpitem->nextSibling())
                        {
                                nick       = tmpitem->text(0);
                                hubname    = tmpitem->text(1);
                                remotefile = tmpitem->text(2);
                                if ( DLM_QueueRemove(nick.toAscii().data(),hubname.toAscii().data(),remotefile.toAscii().data()) == FALSE )
                                {
                                        // TODO: error handling
                                }
                        }
                }
                if ( DLM_QueueRemove(nick.toAscii().data(),hubname.toAscii().data(),remotefile.toAscii().data()) == FALSE )
                {
                        // TODO: error handling
                }
        }
	else if ( chosen == info )
	{
		DCFileTransferInfo * ft;

		ft = new DCFileTransferInfo(localfile.latin1());
		ft->exec();
		delete ft;
	}
	else if ( chosen == clone )
	{
		if ( remotefile.isEmpty() )
			SearchFileClone(localfile, size);
		else
			SearchFileClone(remotefile, size);
	}
	else if ( chosen == clonetth )
	{
		g_pHubSearch->Combobox_SEARCH->setEditText(pFileChunk->m_sHash.Data());
		g_pHubSearch->LineEdit_SEARCHSIZE->setText("0");
		g_pHubSearch->ComboBox_SEARCHTYPE->setCurrentItem(9);
		g_pHubSearch->ComboBox_SEARCHUNIT->setCurrentItem(0);
		g_pHubSearch->ComboBox_SEARCHLIMIT->setCurrentItem(0);
		
		if ( g_pHubSearch->isMinimized() )
		{
			g_pHubSearch->showNormal();
		}
		else if ( g_pHubSearch->isVisible()==FALSE )
		{
			g_pHubSearch->setEnabled(TRUE);
			g_pHubSearch->show();
		}

		if ( g_pHubSearch->TabWidget_HUBSEARCH->isVisible()==FALSE )
		{
			g_pHubSearch->TabWidget_HUBSEARCH->show();
		}
	}
}

/** */
void DCTransferView::slotDoubleClickedTransferWaitList( Q3ListViewItem * /*item*/ )
{
	Q3ListViewItem * item;
	Q3ListViewItem * item0;
	QString nick;
	QString hubname;
	QString hubhost;
        CUserFileInfo UserFileInfo;

	item = ListView_TRANSFERWAIT->currentItem();

	if (item->depth() == 0)
	{
		item0 = item;
	}
	else
	{
		item0 = item->parent();
	}

	nick    = item0->text(0);
	hubname = item0->text(1);
	hubhost = item0->text(2);

	if (item->depth() == 0)
	{
		if ( g_pConnectionManager->IsHubOnline(hubname.toAscii().data(),hubhost.toAscii().data()) == ehsNONE )
		{
			if ( DLM_QueueUpdateHub( nick.toAscii().data(), hubname.toAscii().data() ) == FALSE )
			{
				// TODO: error message ...
			}
			g_pConnectionManager->Connect( hubname.toAscii().data(), hubhost.toAscii().data() );
			return;
		}
	}

	if ( DLM_QueueGetFileInfo(nick.toAscii().data(),hubname.toAscii().data(),hubhost.toAscii().data(),"",&UserFileInfo) == FALSE )
	{
		return;
	}

	if ( (UserFileInfo.eWaitState != etwsRUN) && (UserFileInfo.eWaitState != etwsWAIT) )
	{
		if ( DLM_TransferConnect( nick.toAscii().data(), hubname.toAscii().data() ) == FALSE )
		{
			// error message
			QMessageBox::critical( 0, tr("Try Connect"),
				tr("User and Hub not found in the queue !") + "\n\n" +
				tr("Nick:") + " '" +
				nick + "'\n" +
				tr("Hub:") + " '" + hubname + "'\n" );
		}
	}
}

/** */
void DCTransferView::slotContextMenuUserSlotList( const QPoint & )
{
	QList<QTreeWidgetItem*> selected = TreeWidget_SLOTS->selectedItems();
	
	if ( selected.size() == 0 )
	{
		return;
	}
	
	QTreeWidgetItem * item = selected.at(0);
	QAction * chosen = 0;
	QMenu * m;

	if( item == 0 )
	{
		return;
	}

	m = new QMenu(this);

	QAction * remove = DCMenuHandler().addAction( m, emiREMOVE );

        chosen = m->exec(QCursor::pos());

	delete m;

        if ( chosen == remove )
        {
		DLM_AddUserSlot( item->text(0).toAscii().data(), item->text(1).toAscii().data(), 0 );
        }
}

/** */
void DCTransferView::slotRightButtonClickedLog( const QPoint& )
{
	QAction * chosen = 0;
	QMenu *m;
	DCMenuHandler mhandler;

	m = new QMenu(this);

	QAction * copy = mhandler.addAction( m, emiCOPY, m_pTextEdit_LOG->textCursor().hasSelection() );
	QAction * clear = mhandler.addAction( m, emiCLEAR, TRUE );
	QAction * selectall = mhandler.addAction( m, emiSELECT_ALL, TRUE );

        chosen = m->exec(QCursor::pos());

	delete m;

	if ( chosen == copy )
	{
		m_pTextEdit_LOG->copy();
	}
	else if ( chosen == clear )
	{
		m_pTextEdit_LOG->clear();
	}
	else if ( chosen == selectall )
	{
		QTextCursor cursor = m_pTextEdit_LOG->textCursor();
		cursor.select( QTextCursor::Document );
		m_pTextEdit_LOG->setTextCursor( cursor );
	}
}
