/***************************************************************************
                          dchublistmanager.cpp  -  description
                             -------------------
    begin                : Mon Oct 1 2001
    copyright            : (C) 2001-2004 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 "dchublistmanager.h"

#include <stdlib.h>

#include <QApplication>
#include <QObject>
#include <QToolButton>
#include <QLineEdit>
#include <QCursor>
#include <QTabWidget>
#include <QComboBox>
#include <QCheckBox>
#include <QMessageBox>
#include <QClipboard>
#include <QResizeEvent>
#include <QShowEvent>
#include <QEvent>
#include <QMdiArea>
#include <QMdiSubWindow>
#include <QHeaderView>

#include <vector>

#include "dcmenuhandler.h"
#include "dchubprofile.h"
#include "dchubfilter.h"
#include "dciconloader.h"
#include "dcconnectionmanager.h"
#include "dcconfig.h"
#include "dchublistitems.h"
#include "dcguiutils.h"

#include <dclib/dcos.h>
#include <dclib/core/cstringlist.h>
#include <dclib/dcobject.h>

#include "dceditserver.h"
#include "cdialogmessage.h"
#include "publichubsmodel.h"
#include "publichubsproxy.h"

DCHubListManager * g_pHubListManager = 0;

/** */
DCHubListManager::DCHubListManager( QWidget * parent ) : QWidget( parent )
{
	setupUi(this);

	/* icons moved out of .ui files so that they can be themed */
	ToolButton_ADDFILTER->setIcon( QIcon( g_pIconLoader->GetPixmap(eiEDITADD) ) );
	ToolButton_EDITFILTER->setIcon( QIcon( g_pIconLoader->GetPixmap(eiEDIT) ) );
	ToolButton_DELFILTER->setIcon( QIcon( g_pIconLoader->GetPixmap(eiEDITDELETE) ) );
	ToolButton_RELOADPUBLICHUBLIST->setIcon( QIcon( g_pIconLoader->GetPixmap(eiRELOAD) ) );
	ToolButton_UPDATEPUBLICHUBLIST->setIcon( QIcon( g_pIconLoader->GetPixmap(eiUPDATE) ) );
	ToolButton_CONNECT->setIcon( QIcon( g_pIconLoader->GetPixmap(eiCONNECT) ) );

	/* ... and for bookmark buttons */
	ToolButton_BOOKMARK_SAVE->setIcon( QIcon( g_pIconLoader->GetPixmap(eiSAVE) ) );
	ToolButton_BOOKMARK_ENABLE_SORT->setIcon( QIcon( g_pIconLoader->GetPixmap(eiSORT_DOWN_ARROW) ) );
	ToolButton_BOOKMARK_ADD->setIcon( QIcon( g_pIconLoader->GetPixmap(eiEDITADD) ) );
	ToolButton_BOOKMARK_EDIT->setIcon( QIcon( g_pIconLoader->GetPixmap(eiEDIT) ) );
	ToolButton_BOOKMARK_DEL->setIcon( QIcon( g_pIconLoader->GetPixmap(eiEDITDELETE) ) );
	
	lastPublicHubsWidth = -1;
	lastBookmarkHubsWidth = -1;

	/* we have custom column resizing code */
	TreeView_PUBLIC->header()->setStretchLastSection(false);
	TreeWidget_BOOKMARKS->header()->setStretchLastSection(false);

	// set default icon
	setWindowIcon( g_pIconLoader->GetPixmap(eiSERVER) );

	if ( (parent != 0) && (qobject_cast<QMdiArea*>(parent) != 0) )
	{
		m_pContainerWindow = new QMdiSubWindow();
		m_pContainerWindow->setWidget(this);
	}
	else
	{
		m_pContainerWindow = 0;
	}

	model = new PublicHubsModel( this );
	proxy = new PublicHubsProxy( this );
	proxy->setSortRole( PublicHubsProxyRole );
	proxy->setSortCaseSensitivity( Qt::CaseInsensitive );
	proxy->setFilterRole( PublicHubsProxyRole );
	proxy->setFilterCaseSensitivity( Qt::CaseInsensitive );
	proxy->setSourceModel( model );
	TreeView_PUBLIC->setModel( proxy );
	
	m_pMessageList = new QList<CDCMessage*>();

	InitDocument();

	g_pHubListManager = this;
}

/** */
DCHubListManager::~DCHubListManager()
{
	g_pHubListManager = NULL;

	m_HLMMutex.lock();

	if ( m_pMessageList )
	{
		QList<CDCMessage*> * tmp = m_pMessageList;
		m_pMessageList = 0;
		
		for ( QList<CDCMessage*>::const_iterator it = tmp->constBegin(); it != tmp->constEnd(); ++it )
		{
			delete *it;
		}
		
		delete tmp;
	}

	m_HLMMutex.unlock();
	
	/* models deleted by QObject auto child deletion */
	
	// we might have removed public hubs
	if ( g_pConfig->GetRemovePublicHubEnabled() )
	{
		g_pConfig->SaveDCPublicHub();
	}
	
	// bookmarks may have been sorted and the new order needs to be saved
	updateBookmarkOrder();
	
	/* delete all hub filter objects */
	for ( QMap<QString, DC_HubFilterObject*>::const_iterator it = m_HubFilterMap.constBegin(); it != m_HubFilterMap.constEnd(); ++it )
	{
		delete it.value();
	}
	m_HubFilterMap.clear();
	
	if ( m_pContainerWindow )
	{
		m_pContainerWindow->setWidget(0); // otherwise the QMdiSubWindow will delete this again
		delete m_pContainerWindow;
		m_pContainerWindow = 0;
	}
}

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

/** overridden so that the column widths are initialized on first show() */
void DCHubListManager::showEvent( QShowEvent * event )
{
	QWidget::showEvent( event );

	if ( isVisible() )
	{
		SizeColumnsPreservingRatios();
	}
}

/** resize event handler */
void DCHubListManager::resizeEvent( QResizeEvent * )
{
	SizeColumnsPreservingRatios();
}

/** */
void DCHubListManager::closeEvent( QCloseEvent * e )
{
        emit onDie(this);
	QWidget::closeEvent( e );
	
	if ( m_pContainerWindow && m_pContainerWindow->parent() )
	{
		/* Using QMdiArea::removeSubWindow() breaks tabs mode but this works */
		m_pContainerWindow->setParent(0);
	}
}

/** Initialize or adjust widths of the ListView columns */
void DCHubListManager::SizeColumnsPreservingRatios()
{
	int width;
	
	if ( TreeView_PUBLIC->isVisible() )
	{
		width = TreeView_PUBLIC->width();
		if ( width > 0 )
		{
			if ( lastPublicHubsWidth == -1 )
			{
				/* set initial widths using default ratios */
				/* also expand the list view since we have lots of columns now */
				TreeView_PUBLIC->setColumnWidth( 0, ((width*3)/10) );
				TreeView_PUBLIC->setColumnWidth( 1, ((width*3)/10) );
				TreeView_PUBLIC->setColumnWidth( 2, ((width*3)/10) );
				TreeView_PUBLIC->setColumnWidth( 3, ((width*1)/10) );
				TreeView_PUBLIC->setColumnWidth( 4, ((width*2)/10) );
				TreeView_PUBLIC->setColumnWidth( 5, ((width*1)/10) );
				TreeView_PUBLIC->setColumnWidth( 6, ((width*1)/10) );
				TreeView_PUBLIC->setColumnWidth( 7, ((width*3)/10) );
				
				lastPublicHubsWidth = TreeView_PUBLIC->width();
			}
			else if ( lastPublicHubsWidth != width )
			{
				DCGuiUtils::AdjustColumnWidths( TreeView_PUBLIC, lastPublicHubsWidth );			
				lastPublicHubsWidth = TreeView_PUBLIC->width();
			}
		}
	}
	else if ( TreeWidget_BOOKMARKS->isVisible() )
	{
		width = TreeWidget_BOOKMARKS->width();
		if ( width > 0 )
		{
			if ( lastBookmarkHubsWidth == -1 )
			{
				TreeWidget_BOOKMARKS->setColumnWidth( 0, width/3 );
				TreeWidget_BOOKMARKS->setColumnWidth( 1, width/3 );
				TreeWidget_BOOKMARKS->setColumnWidth( 2, width/3 );
				
				lastBookmarkHubsWidth = TreeWidget_BOOKMARKS->width();
			}
			else if ( lastBookmarkHubsWidth != width )
			{
				DCGuiUtils::AdjustColumnWidths( TreeWidget_BOOKMARKS, lastBookmarkHubsWidth );
				lastBookmarkHubsWidth = TreeWidget_BOOKMARKS->width();
			}
		}
	}
}

/** */
void DCHubListManager::SetToolBar( QFrame * frame1, QFrame * frame2, bool vis )
{
	if ( vis )
	{
		frame1->hide();
		frame1->setEnabled(false);
		frame2->show();
		frame2->setEnabled(true);
	}
	else
	{
		frame2->hide();
		frame2->setEnabled(false);
		frame1->show();
		frame1->setEnabled(true);
	}
}

/** */
void DCHubListManager::InitDocument()
{
	StringMap * map;
	bool btb1=true,btb2=true;
	bool bfilter=false;

	DC_HubFilterObject * HubFilterObject;

	// hide progressbar
	ProgressBar_LOADHUBLIST->setMinimum(0);
	ProgressBar_LOADHUBLIST->hide();

	// set bookmark icon
	TabWidget_SERVERLIST->setTabIcon( 1, QIcon( g_pIconLoader->GetPixmap(eiBOOKMARK_FOLDER) ) );

	// init the toolbars
	Frame_TOOLBAR1_HIDE->installEventFilter(this);
	Frame_TOOLBAR1_SHOW->installEventFilter(this);
	Frame_TOOLBAR2_HIDE->installEventFilter(this);
	Frame_TOOLBAR2_SHOW->installEventFilter(this);
	
	// restore settings
	if ( g_pConfig->GetMap("HUBVIEW",map) )
	{
		if ( ((*map)["WIDTH"].toInt() > 0) && ((*map)["HEIGHT"].toInt() > 0) )
		{
			if ( m_pContainerWindow != 0 )
			{
				m_pContainerWindow->setGeometry( (*map)["X"].toInt(), (*map)["Y"].toInt(), (*map)["WIDTH"].toInt(), (*map)["HEIGHT"].toInt() );
			}
		}

		if ( (!((*map)["TOOLBAR1"].isEmpty())) && ((*map)["TOOLBAR1"].toInt() == 0) )
		{
			btb1 = false;
		}

		if ( (!((*map)["TOOLBAR2"].isEmpty())) && ((*map)["TOOLBAR2"].toInt() == 0) )
		{
			btb2 = false;
		}

		// restore active page
		TabWidget_SERVERLIST->setCurrentIndex((*map)["ACTIVEPAGE"].toInt());
		// restore linedit
		LineEdit_SERVER->setText((*map)["LE_SERVER"]);
		
		/* restore sorting parameters */
		TreeView_PUBLIC->sortByColumn( (*map)["PUBLICSORTCOLUMN"].toInt(), DCGuiUtils::SortOrderFromName((*map)["PUBLICSORTORDER"]) );
		
		if ( (!((*map)["BOOKMARKSORTINGENABLED"].isEmpty())) && ((*map)["BOOKMARKSORTINGENABLED"].toInt() == 0) )
		{
			TreeWidget_BOOKMARKS->setSortingEnabled( false );
		}
		else
		{
			TreeWidget_BOOKMARKS->setSortingEnabled( true );
		}
		
		TreeWidget_BOOKMARKS->sortItems( (*map)["BOOKMARKSORTCOLUMN"].toInt(), DCGuiUtils::SortOrderFromName((*map)["BOOKMARKSORTORDER"]) );
	}

	SetToolBar( Frame_TOOLBAR1_HIDE, Frame_TOOLBAR1_SHOW, btb1 );
	SetToolBar( Frame_TOOLBAR2_HIDE, Frame_TOOLBAR2_SHOW, btb2 );

	connect( LineEdit_SERVER, SIGNAL(returnPressed()), this, SLOT(slotConnect()) );
	connect( ToolButton_RELOADPUBLICHUBLIST, SIGNAL(clicked()), this, SLOT(slotReloadPublicHubList()) );
	connect( ToolButton_UPDATEPUBLICHUBLIST, SIGNAL(clicked()), this, SLOT(slotUpdatePublicHubList()) );
	connect( ToolButton_CONNECT, SIGNAL(clicked()), this, SLOT(slotConnect()) );

	// public list
	connect( TreeView_PUBLIC,SIGNAL(activated( const QModelIndex & )), this, SLOT(slotItemActivatedPublic( const QModelIndex & )) );
	connect( TreeView_PUBLIC,SIGNAL(customContextMenuRequested( const QPoint & )), this, SLOT(slotContextMenuPublicList( const QPoint & )) );

	// bookmark list
	connect( TreeWidget_BOOKMARKS,SIGNAL(itemActivated( QTreeWidgetItem *, int )), this, SLOT(slotItemActivatedBookmarks( QTreeWidgetItem *, int)) );
	connect( TreeWidget_BOOKMARKS,SIGNAL(customContextMenuRequested( const QPoint & )), this, SLOT(slotContextMenuBookmarkList( const QPoint & )) );
	connect( ToolButton_BOOKMARK_UP, SIGNAL(clicked()), this, SLOT(slotMoveBookmarkUp()) );
	connect( ToolButton_BOOKMARK_DOWN, SIGNAL(clicked()), this, SLOT(slotMoveBookmarkDown()) );
	connect( ToolButton_BOOKMARK_ENABLE_SORT, SIGNAL(clicked()), this, SLOT(slotEnableBookmarkSorting()) );
	connect( ToolButton_BOOKMARK_SAVE, SIGNAL(clicked()), this, SLOT(slotSaveBookmarks()) );
	connect( ToolButton_BOOKMARK_ADD, SIGNAL(clicked()), this, SLOT(slotAddBookmark()) );
	connect( ToolButton_BOOKMARK_EDIT, SIGNAL(clicked()), this, SLOT(slotEditBookmark()) );
	connect( ToolButton_BOOKMARK_DEL, SIGNAL(clicked()), this, SLOT(slotDelBookmark()) );

	connect( TabWidget_SERVERLIST,SIGNAL(currentChanged(QWidget*)), this, SLOT(slotTabWidgetCurrentChange(QWidget*)) );

	// filter
	connect( ToolButton_ADDFILTER, SIGNAL(clicked()), this, SLOT(slotAddFilter()) );
	connect( ToolButton_EDITFILTER, SIGNAL(clicked()), this, SLOT(slotEditFilter()) );
	connect( ToolButton_DELFILTER, SIGNAL(clicked()), this, SLOT(slotDelFilter()) );
	connect( ComboBox_FILTER, SIGNAL(activated( const QString & )), this, SLOT(slotFilterChange( const QString &)) );

	TreeWidget_BOOKMARKS->setAlternatingRowColors( g_pConfig->GetAlternatingRowColors() );
	TreeView_PUBLIC->setAlternatingRowColors( g_pConfig->GetAlternatingRowColors() );
	connect( g_pConfig, SIGNAL( alternatingRowColorsChanged( bool ) ), this, SLOT( slotAltRowColors( bool ) ) );

	connect( &m_Timer, SIGNAL(timeout()), this, SLOT(timerDone()) );

	// load filter
	g_pConfig->LoadDCHubFilter(&m_HubFilterMap);

	// create default
	if ( m_HubFilterMap.isEmpty() )
	{
		HubFilterObject = new DC_HubFilterObject();

		HubFilterObject->m_sFilterName = "Default";

		m_HubFilterMap.insert( HubFilterObject->m_sFilterName, HubFilterObject );

		g_pConfig->SaveDCHubFilter(&m_HubFilterMap);
	}

	for ( QMap<QString, DC_HubFilterObject*>::const_iterator it = m_HubFilterMap.constBegin(); it != m_HubFilterMap.constEnd(); ++it )
	{
		HubFilterObject = it.value();
		
		ComboBox_FILTER->addItem( HubFilterObject->m_sFilterName );

		if ( (*map)["FILTER"] == HubFilterObject->m_sFilterName )
		{
			bfilter = true;
		}
	}

	// restore filter
	if ( bfilter )
	{
		int index = ComboBox_FILTER->findText((*map)["FILTER"]);
		if ( index != -1 )
		{
			ComboBox_FILTER->setCurrentIndex(index);
		}
	}
	else
	{
		int index = ComboBox_FILTER->findText("Default");
		if ( index != -1 )
		{
			ComboBox_FILTER->setCurrentIndex(index);
		}
	}

	ShowBookmarkList();
	ShowPublicHubList();

	m_Timer.setSingleShot( true );
	m_Timer.start( 500 );
}

/** */
void DCHubListManager::DeInitDocument()
{
	StringMap * map;

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

	if ( m_pContainerWindow != 0 )
	{
		(*map)["X"]          = QString().setNum(m_pContainerWindow->x());
		(*map)["Y"]          = QString().setNum(m_pContainerWindow->y());
		(*map)["WIDTH"]      = QString().setNum(m_pContainerWindow->width());
		(*map)["HEIGHT"]     = QString().setNum(m_pContainerWindow->height());
		(*map)["VISIBLE"]    = QString().setNum(m_pContainerWindow->isVisible());
		(*map)["MAXIMIZED"]  = QString().setNum(m_pContainerWindow->isMaximized());
		(*map)["MINIMIZED"]  = QString().setNum(m_pContainerWindow->isMinimized());
	}
	(*map)["ACTIVEPAGE"] = QString().setNum(TabWidget_SERVERLIST->currentIndex());
	(*map)["LE_SERVER"]  = LineEdit_SERVER->text();
	(*map)["FILTER"]     = ComboBox_FILTER->currentText();

	if ( !isEnabled() )
	{
		setEnabled(true);
	}

	(*map)["TOOLBAR1"]  = QString().setNum(Frame_TOOLBAR1_SHOW->isEnabled());
	(*map)["TOOLBAR2"]  = QString().setNum(Frame_TOOLBAR2_SHOW->isEnabled());
	
	(*map)["PUBLICSORTCOLUMN"] = QString().setNum( TreeView_PUBLIC->header()->sortIndicatorSection() );
	(*map)["PUBLICSORTORDER"]  = DCGuiUtils::SortOrderName( TreeView_PUBLIC->header()->sortIndicatorOrder() );
	
	(*map)["BOOKMARKSORTCOLUMN"] = QString().setNum(TreeWidget_BOOKMARKS->sortColumn());
	(*map)["BOOKMARKSORTORDER"]  = DCGuiUtils::SortOrderName( TreeWidget_BOOKMARKS->header()->sortIndicatorOrder() );
	(*map)["BOOKMARKSORTINGENABLED"] = QString().setNum(TreeWidget_BOOKMARKS->isSortingEnabled());
}

/** event filter */
bool DCHubListManager::eventFilter(QObject* object, QEvent* event)
{
	if ( event->type() == QEvent::MouseButtonDblClick )
	{
		if ( object == Frame_TOOLBAR1_HIDE )
		{
			SetToolBar( Frame_TOOLBAR1_HIDE, Frame_TOOLBAR1_SHOW, true );
		}
		else if ( object == Frame_TOOLBAR1_SHOW )
		{
			SetToolBar( Frame_TOOLBAR1_HIDE, Frame_TOOLBAR1_SHOW, false );
		}
		else if ( object == Frame_TOOLBAR2_HIDE )
		{
			SetToolBar( Frame_TOOLBAR2_HIDE, Frame_TOOLBAR2_SHOW, true );

			// show progressbar
			if ( m_pHubListUrl != 0 )
				ProgressBar_LOADHUBLIST->show();
		}
		else if ( object == Frame_TOOLBAR2_SHOW )
		{
			SetToolBar( Frame_TOOLBAR2_HIDE, Frame_TOOLBAR2_SHOW, false );
		}
	}

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

/** callback function */
int DCHubListManager::DC_CallBack( CDCMessage * DCMessage )
{
	int err = -1;

	m_HLMMutex.lock();

	if ( DCMessage && m_pMessageList )
	{
		m_pMessageList->append(DCMessage);
		err = 0;
	}

	m_HLMMutex.unlock();

	return err;
}

/** */
void DCHubListManager::timerDone()
{
	CDCMessage * DCMsg;
	int i;

	for(i=0;i<50;i++)
	{
		if ( m_HLMMutex.tryLock() == false )
		{
			break;
		}

		if ( m_pMessageList && !m_pMessageList->isEmpty() )
		{
			DCMsg = m_pMessageList->takeFirst();
		}
		else
		{
			DCMsg = 0;
		}

		m_HLMMutex.unlock();

		if ( DCMsg == 0 )
		{
			break;
		}

		switch ( DCMsg->m_eType )
		{
			case DC_MESSAGE_GETHUBLIST:
			{
				DCMessageGetHubList * msg = (DCMessageGetHubList*) DCMsg;

				if ( msg->m_bRun == false )
				{
					// enable buttons
					ToolButton_RELOADPUBLICHUBLIST->setEnabled(true);
					ToolButton_UPDATEPUBLICHUBLIST->setEnabled(true);

					// hide progressbar
					ProgressBar_LOADHUBLIST->hide();

					ShowPublicHubList();
				}
				else
				{
					// disable buttons
					ToolButton_RELOADPUBLICHUBLIST->setEnabled(false);
					ToolButton_UPDATEPUBLICHUBLIST->setEnabled(false);

					// show progressbar
					ProgressBar_LOADHUBLIST->show();
				}

				break;
			}

			case DC_MESSAGE_TRANSFER:
			{
				CMessageTransfer *msg = (CMessageTransfer*)DCMsg;

				ProgressBar_LOADHUBLIST->setMaximum(msg->m_nLength);
				ProgressBar_LOADHUBLIST->setValue(msg->m_nTransfered);

				break;
			}

			default:
			{
				break;
			}
		}

		if ( DCMsg )
		{
			delete DCMsg;
		}
	}

	m_Timer.setSingleShot( true );
	m_Timer.start( 500 );
}

/** */
void DCHubListManager::ShowPublicHubList()
{
	DCConfigHubItem * hubitem = 0;
	CList<DCConfigHubItem> PublicHubList;
	int x = 0;

	// disable filter combo box
	ComboBox_FILTER->setEnabled(false);

	TabWidget_SERVERLIST->setTabText( 0, tr("Public")+" (0/0)" );

	TreeView_PUBLIC->setUpdatesEnabled(false);
	TreeView_PUBLIC->setSortingEnabled(false);
	TreeView_PUBLIC->clearSelection();
	model->clear();

	g_pConfig->GetPublicHubList(&PublicHubList);

	while ( (hubitem=PublicHubList.Next(hubitem)) != 0 )
	{
		++x;

		if ( x == 100 )
		{
			qApp->processEvents();
			x = 0;
		}

		model->addHub(
			QString::fromAscii(hubitem->m_sName.Data()),
			QString::fromAscii(hubitem->m_sHost.Data()),
			QString::fromAscii(hubitem->m_sDescription.Data()),
			hubitem->m_nUserCount,
			QString::fromAscii(hubitem->m_sCountry.Data()),
			hubitem->m_nShared,
			hubitem->m_nMinShare,
			QString::fromAscii(hubitem->m_sExtra.Data())
		);
	}

	TreeView_PUBLIC->setSortingEnabled(true);
	proxy->invalidate();
	slotFilterChange(ComboBox_FILTER->currentText());
	TreeView_PUBLIC->setUpdatesEnabled(true);

	TabWidget_SERVERLIST->setTabText( 0, tr("Public")+" ("+QString().setNum(TreeView_PUBLIC->model()->rowCount())+"/"+QString().setNum(PublicHubList.Count())+")");

	// enable filter combo box
	ComboBox_FILTER->setEnabled(true);
}

/** */
void DCHubListManager::ShowBookmarkList()
{
	int x = 0;
	DCConfigHubItem * hubitem = 0;
	CList<DCConfigHubItem> list;
	bool sortingenabled = TreeWidget_BOOKMARKS->isSortingEnabled();

	g_pConfig->GetBookmarkHubList(&list);

	TreeWidget_BOOKMARKS->setSortingEnabled(false);
	TreeWidget_BOOKMARKS->setUpdatesEnabled(false);
	TreeWidget_BOOKMARKS->clear();

	while( (hubitem=list.Next(hubitem)) != 0 )
	{
		DCBookmarkHubItem * item = new DCBookmarkHubItem( TreeWidget_BOOKMARKS );
		item->setText( 0, hubitem->m_sName.Data() );
		item->setText( 1, hubitem->m_sHost.Data() );
		item->setText( 2, hubitem->m_sDescription.Data() );
		item->position = x;

		x++;

		if ( x == 100 )
		{
			qApp->processEvents();
			x = 0;
		}
	}

	if ( sortingenabled )
	{
		TreeWidget_BOOKMARKS->setSortingEnabled(sortingenabled);
	}
	TreeWidget_BOOKMARKS->setUpdatesEnabled(true);

	TabWidget_SERVERLIST->setTabText( 1, tr("Bookmarks")+" ("+QString().setNum(TreeWidget_BOOKMARKS->model()->rowCount())+")" );
}

/** */
void DCHubListManager::slotReloadPublicHubList()
{
	g_pConfig->ClearPublicHubList();

	GetPublicHubList();
}

/** update public hub list */
void DCHubListManager::slotUpdatePublicHubList()
{
	GetPublicHubList();
}

/** */
void DCHubListManager::slotItemActivatedPublic( const QModelIndex & index )
{
	PublicHubItem * item = model->getItem( proxy->mapToSource( index ) );
	
	if ( item )
		g_pConnectionManager->Connect( item->name.toAscii().constData(), item->server.toAscii().constData() );
}

/** */
void DCHubListManager::slotItemActivatedBookmarks( QTreeWidgetItem * item, int /* column */ )
{
	if ( item )
		g_pConnectionManager->Connect( item->text(0).toAscii().constData(), item->text(1).toAscii().constData() );
}

/** */
void DCHubListManager::slotConnect()
{
	g_pConnectionManager->Connect( CString(), LineEdit_SERVER->text().toAscii().constData() );
}

/** */
void DCHubListManager::slotAddFilter()
{
	DC_HubFilterObject * HubFilterObject;
	DCHubFilter * hf;

	hf = new DCHubFilter(this);

	if ( hf->exec() == QDialog::Accepted )
	{
		HubFilterObject = new  DC_HubFilterObject();

		// get the new data
		hf->Get( HubFilterObject );

		if ( HubFilterObject->m_sFilterName.isEmpty() )
		{
			// todo: error message

			delete HubFilterObject;
		}
		else if ( m_HubFilterMap.contains( HubFilterObject->m_sFilterName ) )
		{
			QMessageBox::information(
				this,
				tr("Add hub filter"),
				tr("A filter with that name already exists")
			);

			delete HubFilterObject;
		}
		else
		{
			m_HubFilterMap.insert( HubFilterObject->m_sFilterName, HubFilterObject );

			ComboBox_FILTER->addItem( HubFilterObject->m_sFilterName );
		}

		g_pConfig->SaveDCHubFilter(&m_HubFilterMap);

		delete hf;
	}
}

/** */
void DCHubListManager::slotEditFilter()
{
	QString s;
	DC_HubFilterObject * HubFilterObject;
	DCHubFilter * hf;

	s = ComboBox_FILTER->currentText();

	if ( (!(s.isEmpty())) && (s != "Default") )
	{
		HubFilterObject = m_HubFilterMap.value( s );
		if ( HubFilterObject != 0 )
		{
			hf = new DCHubFilter(this);

			hf->Edit( HubFilterObject );

			if ( hf->exec() == QDialog::Accepted )
			{
				// get the new data
				hf->Get( HubFilterObject );

				if ( HubFilterObject->m_sFilterName.isEmpty() )
				{
					HubFilterObject->m_sFilterName = s;

					// todo: error message
				}
				else if ( s != HubFilterObject->m_sFilterName )
				{
					if ( m_HubFilterMap.contains( HubFilterObject->m_sFilterName ) )
					{
						QMessageBox::information(
							this,
							tr("Edit hub filter"),
							tr("A filter with that name already exists")
						);
						HubFilterObject->m_sFilterName = s;
					}
					else
					{
						/* not deleted because it's the same pointer */
						m_HubFilterMap.remove(s);
						m_HubFilterMap.insert( HubFilterObject->m_sFilterName, HubFilterObject );

						ComboBox_FILTER->setItemText( ComboBox_FILTER->currentIndex(), HubFilterObject->m_sFilterName );
					}
				}

				// update view
				slotFilterChange( HubFilterObject->m_sFilterName );

				g_pConfig->SaveDCHubFilter(&m_HubFilterMap);
			}

			delete hf;
		}
	}
}

/** */
void DCHubListManager::slotDelFilter()
{
	QString s = ComboBox_FILTER->currentText();

	if ( (!(s.isEmpty())) && (s != "Default") )
	{
		ComboBox_FILTER->removeItem(ComboBox_FILTER->currentIndex());

		QMap<QString, DC_HubFilterObject*>::const_iterator it = m_HubFilterMap.find( s );
		if ( it != m_HubFilterMap.constEnd() )
		{
			delete it.value();
			m_HubFilterMap.remove( s );
			g_pConfig->SaveDCHubFilter(&m_HubFilterMap);
		}
		else
		{
			QMessageBox::warning(
				this,
				tr("Delete hub filter"),
				tr("Filter not found")
			);
		}
	}
}

/** */
void DCHubListManager::slotFilterChange( const QString & s )
{
	if ( !s.isEmpty() )
	{
		DC_HubFilterObject * filter = m_HubFilterMap.value(s);
		if ( filter )
		{
			proxy->setFilter( filter );
			TabWidget_SERVERLIST->setTabText( 0, tr("Public")+" ("+QString().setNum(TreeView_PUBLIC->model()->rowCount())+"/"+QString().setNum(g_pConfig->GetPublicHubListSize())+")");
		}
	}
}

/** */
void DCHubListManager::RemoveBookmark( QTreeWidgetItem * item )
{
	if ( g_pConfig->RemoveBookmarkHub( item->text(0).toAscii().constData(), item->text(1).toAscii().constData(), item->text(2).toAscii().constData() ) )
	{
		g_pConfig->SaveDCBookHub();
		
		QTreeWidgetItemIterator it( TreeWidget_BOOKMARKS );
		DCBookmarkHubItem * removed = (DCBookmarkHubItem*) item;
		for ( ; (*it); ++it )
		{
			DCBookmarkHubItem * current = (DCBookmarkHubItem*) (*it);
			if ( current->position > removed->position )
			{
				current->position--;
			}
		}

		delete item;

		// update tabbar
		TabWidget_SERVERLIST->setTabText( 1, tr("Bookmarks")+" ("+QString().setNum(TreeWidget_BOOKMARKS->model()->rowCount())+")" );
	}
}

/** */
void DCHubListManager::AddBookmark( QString hubname, QString hubhost, QString description )
{
	if ( g_pConfig->AddBookmarkHub( hubname.toAscii().constData(), hubhost.toAscii().constData(), description.toAscii().constData() ) )
	{
		g_pConfig->SaveDCBookHub();

		DCBookmarkHubItem * item = new DCBookmarkHubItem( TreeWidget_BOOKMARKS );
		item->setText( 0, hubname );
		item->setText( 1, hubhost );
		item->setText( 2, description );
		item->position = TreeWidget_BOOKMARKS->topLevelItemCount() - 1;

		// update tabbar
		TabWidget_SERVERLIST->setTabText( 1, tr("Bookmarks")+" ("+QString().setNum(TreeWidget_BOOKMARKS->model()->rowCount())+")" );
	}
}

/** */
void DCHubListManager::UpdateBookmark( QString hubname, QString hubhost, QString description )
{
	if ( g_pConfig->UpdateBookmarkHub( hubname.toAscii().constData(), hubhost.toAscii().constData(), description.toAscii().constData() ) )
	{
		g_pConfig->SaveDCBookHub();
	}
}

/** */
CStringList<CString> * DCHubListManager::GetFilteredHubList()
{
	CStringList<CString> * list = new CStringList<CString>();

	for ( int i = 0; i < proxy->rowCount(); ++i )
	{
		
		CString addr = proxy->data( proxy->index(i,1) ).toString().toAscii().constData();
		CString * string = 0;
		
		if ( list->Get( addr, &string ) != 0 )
		{
			list->Add( addr, new CString( addr ) );
		}
	}

	if ( list->Count() == 0 )
	{
		delete list;
		list = 0;
	}

	return list;
}

/** */
void DCHubListManager::slotContextMenuBookmarkList( const QPoint & )
{
	QTreeWidgetItem * curitem;
	QList<QTreeWidgetItem*> selitems = TreeWidget_BOOKMARKS->selectedItems();
	QMenu * m = new QMenu(this);

	QAction * connect = DCMenuHandler::addAction( m, emiCONNECT, (selitems.count() > 0) );
	DCMenuHandler::addAction( m, emiSEPARATOR );
	QAction * add = DCMenuHandler::addAction( m, emiADD );
	QAction * edit = DCMenuHandler::addAction( m, emiEDIT, (selitems.count() == 1) );
	QAction * remove = DCMenuHandler::addAction( m, emiREMOVE, (selitems.count() > 0) );
	DCMenuHandler::addAction( m, emiSEPARATOR );
	QAction * updserver = DCMenuHandler::addAction( m, emiUPDATE_SERVER, (selitems.count() > 0) );
	QAction * updall = DCMenuHandler::addAction( m, emiUPDATE_ALL_SERVER );
	DCMenuHandler::addAction( m, emiSEPARATOR );
	QAction * profiles = DCMenuHandler::addAction( m, emiHUB_PROFILE_EDITOR );

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

	delete m;

	if ( chosen == 0 )
	{
		return;
	}

	if ( chosen == add )
	{
		slotAddBookmark();
	}
	else if ( chosen == edit )
	{
		slotEditBookmark();
	}
	else if ( chosen == remove )
	{
		if ( queryRemoveBookmarks() == 1 )
		{
			return;
		}
		
		DCConfigHubProfile hubprofile;
	        for ( int i = 0; i < selitems.size(); i++ )
	        {
			curitem = selitems.at(i);
			
			// remove profile for that entry
			if ( g_pConfig->GetHubProfile( curitem->text(0).toAscii().constData(), &hubprofile ) )
			{
				g_pConfig->DelHubProfile( hubprofile.m_sName );
			}

			// remove bookmark
			RemoveBookmark(curitem);
		}
		
		// save changes to profile list, some may have been deleted
		g_pConfig->SaveHubProfile();
		
		// update myinfo
		g_pConnectionManager->SendMyInfoToConnectedServers();
	}
	else if ( chosen == connect )
	{
	        for ( int i = 0; i < selitems.size(); i++ )
	        {
			curitem = selitems.at(i);
			
			g_pConnectionManager->Connect( curitem->text(0).toAscii().constData(), curitem->text(1).toAscii().constData() );
		}
	}
	else if ( chosen == updserver )
	{
		DCConfigHubItem hubitem;

	        for ( int i = 0; i < selitems.size(); i++ )
	        {
			curitem = selitems.at(i);
			
			if ( g_pConfig->GetPublicHub( curitem->text(0).toAscii().constData(), &hubitem ) )
			{
				UpdateBookmark( hubitem.m_sName.Data(), hubitem.m_sHost.Data(), hubitem.m_sDescription.Data() );
				curitem->setText(1,hubitem.m_sHost.Data());
				curitem->setText(2,hubitem.m_sDescription.Data());
			}
		}
	}
	else if ( chosen == updall )
	{
		DCConfigHubItem * hubitem = 0;
		DCConfigHubItem hubitem1;
		CList<DCConfigHubItem> list;

		g_pConfig->GetBookmarkHubList(&list);

		while( (hubitem=list.Next(hubitem)) != 0 )
		{
			if ( g_pConfig->GetPublicHub( hubitem->m_sName, &hubitem1 ) )
			{
				g_pConfig->UpdateBookmarkHub( hubitem1.m_sName, hubitem1.m_sHost, hubitem1.m_sDescription );
			}
		}

		g_pConfig->SaveDCBookHub();

		ShowBookmarkList();
	}
	else if ( chosen == profiles )
	{
		DCHubProfile * dlg = new DCHubProfile(this);

		dlg->exec();

		delete dlg;
		
		// update myinfo
		g_pConnectionManager->SendMyInfoToConnectedServers();
	}
}

/** */
void DCHubListManager::slotContextMenuPublicList( const QPoint & pos )
{
	QList<PublicHubItem*> selitems;
	PublicHubItem * curitem = 0;
	QModelIndexList indexlist = TreeView_PUBLIC->selectionModel()->selectedIndexes();
	
	for ( QModelIndexList::const_iterator it = indexlist.constBegin(); it != indexlist.constEnd(); ++it )
	{
		curitem = model->getItem( proxy->mapToSource( *it ) );
		
		if ( curitem && (selitems.contains( curitem ) == false) )
		{
			selitems.append( curitem );
		}
	}
	
	int numSelected = selitems.size();
	
	if ( numSelected == 0 )
	{
		return;
	}

	QMenu * m = new QMenu(this);

	QAction * connect = DCMenuHandler::addAction( m, emiCONNECT );
	DCMenuHandler::addAction( m, emiSEPARATOR );
	
	QAction * remove = 0;
	if ( g_pConfig->GetRemovePublicHubEnabled() )
	{
		remove = DCMenuHandler::addAction( m, emiREMOVE );
		DCMenuHandler::addAction( m, emiSEPARATOR );
	}
	
	QAction * bookmark = DCMenuHandler::addAction( m, emiADD_BOOKMARK );
	DCMenuHandler::addAction( m, emiSEPARATOR );
	QAction * copycol = DCMenuHandler::addAction( m, emiCOPY_COLUMN_TO_CLIPBOARD, (numSelected == 1) );
	QAction * copyrow = DCMenuHandler::addAction( m, emiCOPY_ROW_TO_CLIPBOARD, (numSelected == 1) );

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

	delete m;

	if ( chosen == 0 )
	{
		return;
	}

	if ( chosen == connect )
	{
	        for ( QList<PublicHubItem*>::const_iterator it = selitems.constBegin(); it != selitems.constEnd(); ++it )
	        {
			curitem = *it;
			g_pConnectionManager->Connect( curitem->name.toAscii().constData(), curitem->server.toAscii().constData() );
		}
	}
	else if ( chosen == remove )
	{
		for ( QList<PublicHubItem*>::const_iterator it = selitems.constBegin(); it != selitems.constEnd(); ++it )
		{
			curitem = *it;
			
			if ( g_pConfig->RemovePublicHub(curitem->name.toAscii().constData(),curitem->server.toAscii().constData(),curitem->description.toAscii().constData()) )
			{
				model->deleteHub(curitem); // don't really need to check this return value too
			}
			else
			{
				QMessageBox::warning(
					this,tr("Remove public hub"),
					tr("Error removing hub \"") + curitem->name + "\" (" + curitem->server + ")"
				);
			}
		}
		
		proxy->invalidate();
		slotFilterChange( ComboBox_FILTER->currentText() );
		
		TabWidget_SERVERLIST->setTabText( 0, tr("Public")+" ("+QString().setNum(TreeView_PUBLIC->model()->rowCount())+"/"+QString().setNum(g_pConfig->GetPublicHubListSize())+")");
	}
	else if ( chosen == bookmark )
	{
	        for ( QList<PublicHubItem*>::const_iterator it = selitems.constBegin(); it != selitems.constEnd(); ++it )
	        {
			curitem = *it;
			AddBookmark( curitem->name, curitem->server, curitem->description );
		}

		TabWidget_SERVERLIST->setTabText( 1, tr("Bookmarks")+" ("+QString().setNum(TreeWidget_BOOKMARKS->model()->rowCount())+")" );
	}
	else if ( chosen == copycol )
	{
		int column = TreeView_PUBLIC->columnAt( pos.x() );
		
		curitem = selitems.first();
		
		QString s;
		
		switch ( column )
		{
			case 0:	s = curitem->name;
				break;
			case 1: s = curitem->server;
				break;
			case 2: s = curitem->description;
				break;
			case 3: s = QString().setNum(curitem->users);
				break;
			case 4: s = curitem->country;
				break;
			case 5: s = DCGuiUtils::GetSizeString(curitem->shared);
				break;
			case 6: s = DCGuiUtils::GetSizeString(curitem->minshare);
				break;
			case 7: s = curitem->extra;
				break;
			default: break;
		}
		
		QApplication::clipboard()->setText( s );
	}
	else if ( chosen == copyrow )
	{
		QString s;

		curitem = selitems.first();
		
		s = curitem->name + " " + curitem->server + " "
		  + curitem->description + " " + QString().setNum(curitem->users)
		  + " " + curitem->country + " " + DCGuiUtils::GetSizeString(curitem->shared)
		  + " " + DCGuiUtils::GetSizeString(curitem->minshare)
		  + " " + curitem->extra;

		QApplication::clipboard()->setText(s);
	}
}

/** update CConfig's sorted bookmarks map */
void DCHubListManager::updateBookmarkOrder()
{
	if ( !(TreeWidget_BOOKMARKS->isSortingEnabled()) )
	{
		//printf("updateBookmarkOrder cancelled, widget is not sorted\n");
		return;
	}
	
	const int count = TreeWidget_BOOKMARKS->topLevelItemCount();
	std::vector<int> newpositions(count);
	
	int i = 0;
	QTreeWidgetItemIterator it( TreeWidget_BOOKMARKS );
	for ( ; (*it); ++it )
	{
		DCBookmarkHubItem * item = (DCBookmarkHubItem*) (*it);
		
		//printf("%s %d->%d\n",item->text(0).toAscii().constData(),item->position,i);
		if ( (item->position < 0) || (item->position >= count) )
		{
			printf("updateBookmarkOrder: Existing key for %s out of range at %d\n", item->text(0).toAscii().constData(), item->position);
			return;
		}
		newpositions[item->position] = i;
		item->position = i;
		
		++i;
	}
	
	//printf("call ReorderBookmarkHubs\n");
	
	g_pConfig->ReorderBookmarkHubs( newpositions );
	g_pConfig->SaveDCBookHub();
}

/** */
void DCHubListManager::slotMoveBookmarkUp()
{
	QTreeWidgetItem * item = TreeWidget_BOOKMARKS->currentItem();
	
	if ( !item )
	{
		return;
	}
	
	int oldindex = TreeWidget_BOOKMARKS->indexOfTopLevelItem( item );
	
	if ( oldindex < 1 )
	{
		return;
	}
	
	if ( TreeWidget_BOOKMARKS->isSortingEnabled() )
	{
		updateBookmarkOrder();
		TreeWidget_BOOKMARKS->setSortingEnabled(false);
	}
	
	int newindex = oldindex - 1;
	
	TreeWidget_BOOKMARKS->takeTopLevelItem( oldindex );
	TreeWidget_BOOKMARKS->insertTopLevelItem( newindex, item );
	TreeWidget_BOOKMARKS->setCurrentItem( item );
	
	((DCBookmarkHubItem*) item)->position = newindex;
	((DCBookmarkHubItem*) TreeWidget_BOOKMARKS->topLevelItem( oldindex ))->position = oldindex;
	
	g_pConfig->MoveBookmarkHub( oldindex, newindex );
	
	g_pConfig->SaveDCBookHub();
}

/** */
void DCHubListManager::slotMoveBookmarkDown()
{
	QTreeWidgetItem * item = TreeWidget_BOOKMARKS->currentItem();
	
	if ( !item )
	{
		return;
	}
	
	int oldindex = TreeWidget_BOOKMARKS->indexOfTopLevelItem( item );
	
	if ( (oldindex == -1) || (oldindex > (TreeWidget_BOOKMARKS->topLevelItemCount() - 2)) )
	{
		return;
	}
	
	if ( TreeWidget_BOOKMARKS->isSortingEnabled() )
	{
		updateBookmarkOrder();
		TreeWidget_BOOKMARKS->setSortingEnabled(false);
	}
	
	int newindex = oldindex + 1;
	
	TreeWidget_BOOKMARKS->takeTopLevelItem( oldindex );
	TreeWidget_BOOKMARKS->insertTopLevelItem( newindex, item );
	TreeWidget_BOOKMARKS->setCurrentItem( item );
	
	((DCBookmarkHubItem*) item)->position = newindex;
	((DCBookmarkHubItem*) TreeWidget_BOOKMARKS->topLevelItem( oldindex ))->position = oldindex;
	
	g_pConfig->MoveBookmarkHub( oldindex, newindex );
	
	g_pConfig->SaveDCBookHub();
}

/** */
void DCHubListManager::slotEnableBookmarkSorting()
{
	if ( TreeWidget_BOOKMARKS->isSortingEnabled() )
	{
		return;
	}
	else
	{
		TreeWidget_BOOKMARKS->setSortingEnabled(true);
		// no updateBookmarkOrder() here
	}
}

/** */
void DCHubListManager::slotSaveBookmarks()
{
	/*
	 * Of couse updateBookmarkOrder() could just have been made a slot, but due to the large
	 * number of problems encountered while attempting to have the code in updateBookmarkOrder
	 * called automatically after the QTreeWidget has been sorted ( which appears to be impossible -
	 * you can connect to QAbstractItemModel::layoutChanged() or various QHeaderView signals
	 * but these are called either before the QTreeWidget has been sorted, or worse, during )
	 * so it is not a slot to indicate that it is not called automatically and updateBookmarkOrder()
	 * must be called manually at various points and on shutdown.
	 */
	if ( TreeWidget_BOOKMARKS->isSortingEnabled() )
	{
		updateBookmarkOrder();
	}
	else
	{
		g_pConfig->SaveDCBookHub();
	}
}

/** */
void DCHubListManager::slotAltRowColors( bool enable )
{
	TreeWidget_BOOKMARKS->setAlternatingRowColors( enable );
	TreeView_PUBLIC->setAlternatingRowColors( enable );
}

/** */
void DCHubListManager::slotAddBookmark()
{
	DCEditServer * des = new DCEditServer(this);
	des->setWindowTitle(tr("Add Bookmark"));
	
	//reset values
	des->Reset();
	
	// DCEditServer now checks name and host are not empty
	if ( des->exec() == QDialog::Accepted )
	{
		// add bookmark to the list
		AddBookmark( des->LineEdit_NAME->text(), des->LineEdit_HOST->text(), des->LineEdit_DESCRIPTION->text() );
		
		// check if profiling possible
		if ( des->CheckBox_PROFILE->isChecked() )
		{
			// get profile from dialog
			DCConfigHubProfile hubprofile;
			des->GetProfile(&hubprofile);
			
			// add new profile
			g_pConfig->AddHubProfile( &hubprofile );
			
			// save profile
			g_pConfig->SaveHubProfile();
			
			// set bookmark for that hub
			g_pConfig->SetBookmarkHubProfile(des->LineEdit_NAME->text().toAscii().constData(),des->LineEdit_NAME->text().toAscii().constData());
		}
		else
		{
			// clear profile from that hub
			g_pConfig->SetBookmarkHubProfile(des->LineEdit_NAME->text().toAscii().constData(),CString());
		}
		
		// update myinfo
		g_pConnectionManager->SendMyInfoToConnectedServers();
	}
	
	delete des;
}

/** */
void DCHubListManager::slotEditBookmark()
{
	// edit only for one selected item
	QTreeWidgetItem * curitem = 0;
	QList<QTreeWidgetItem*> selected = TreeWidget_BOOKMARKS->selectedItems();
	if ( !selected.isEmpty() )
	{
		curitem = selected.first();
	}
	
	if ( !curitem )
	{
		return;
	}
	
	bool prof = false;
	DCConfigHubProfile hubprofile;
	DCConfigHubItem ConfigHubItem;
	
	DCEditServer * des = new DCEditServer(this);
	des->setWindowTitle(tr("Edit Bookmark"));
	
	des->LineEdit_NAME->setText(curitem->text(0));
	des->LineEdit_HOST->setText(curitem->text(1));
	des->LineEdit_DESCRIPTION->setText(curitem->text(2));
	
	// hubitem
	if ( g_pConfig->GetBookmarkHub( curitem->text(0).toAscii().constData(), &ConfigHubItem ) )
	{
		if ( ConfigHubItem.m_sProfile.NotEmpty() )
		{
			// get profile
			if ( g_pConfig->GetHubProfile( ConfigHubItem.m_sProfile, &hubprofile ) )
			{
				des->SetProfile(&hubprofile);
				prof = true;
			}
		}
	}
	
	// DCEditServer now checks that name and host are not empty
	if ( des->exec() == QDialog::Accepted  )
	{
		RemoveBookmark( curitem );
		
		if ( prof )
		{
			// remove the profile
			g_pConfig->DelHubProfile( hubprofile.m_sName );
               	}
		
		// add as new bookmark
		AddBookmark( des->LineEdit_NAME->text(), des->LineEdit_HOST->text(), des->LineEdit_DESCRIPTION->text() );
		
		// check if profiling possible
		if ( des->CheckBox_PROFILE->isChecked() )
		{
			// get profile from dialog
			des->GetProfile(&hubprofile);
			
			// add new profile
			g_pConfig->AddHubProfile( &hubprofile );
			
			// save profile
			g_pConfig->SaveHubProfile();
			
			// set bookmark for that hub
			g_pConfig->SetBookmarkHubProfile(des->LineEdit_NAME->text().toAscii().constData(),des->LineEdit_NAME->text().toAscii().constData());
		}
		else
		{
			// remove profile from that hub
			g_pConfig->SetBookmarkHubProfile(des->LineEdit_NAME->text().toAscii().constData(),CString());
		}
		
		// update myinfo
		g_pConnectionManager->SendMyInfoToConnectedServers();
	}
	
	delete des;
}

/** */
void DCHubListManager::slotDelBookmark()
{
	QTreeWidgetItem * curitem = 0;
	QList<QTreeWidgetItem*> selected = TreeWidget_BOOKMARKS->selectedItems();
	if ( !selected.isEmpty() )
	{
		curitem = selected.first();
	}
	
	if ( !curitem || (queryRemoveBookmarks() == 1) )
	{
		return;
	}
	
	// remove profile for that entry
	DCConfigHubProfile hubprofile;
	if ( g_pConfig->GetHubProfile( curitem->text(0).toAscii().constData(), &hubprofile ) )
	{
		g_pConfig->DelHubProfile( hubprofile.m_sName );
	}
		
	// remove bookmark
	RemoveBookmark(curitem);
	
	// save changes to profile list, some may have been deleted
	g_pConfig->SaveHubProfile();
	
	// update myinfo
	g_pConnectionManager->SendMyInfoToConnectedServers();
}

int DCHubListManager::queryRemoveBookmarks()
{
	StringMap * map;
	int i;
	
	if ( g_pConfig->GetMap("DIALOG_REMOVE_BOOKMARK",map) == false )
	{
		(*map)["SHOW"]    = QString::number(1);
		(*map)["DEFAULT"] = QString::number(0);
	}
	
	if ( ((*map)["SHOW"].toInt() == 1) || ((*map)["DEFAULT"].toInt() == 1) )
	{
		CDialogMessage * dlg = new CDialogMessage(
			this,
			QMessageBox::Warning,
			tr("Remove bookmarks"),
        		tr("You are sure ?"),
			tr("Remove"),
			tr("Cancel")
		);
		
		i = dlg->exec();
		
		(*map)["SHOW"]    = QString::number(!dlg->GetCheckBoxStatus());
		(*map)["DEFAULT"] = QString::number(i);
		
		delete dlg;
	}
	else
	{
		i = (*map)["DEFAULT"].toInt();
	}
	
	return i;
}
