/***************************************************************************
                          dcgui.cpp  -  description
                             -------------------
    begin                : Mon Okt  1 19:59:45 CEST 2001
    copyright            : (C) 2001-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 "dcgui.h"

// Qt includes
#include <QApplication>
#include <QAction>
#include <QComboBox>
#include <QDialog>
#include <QFile>
#include <QLabel>
#include <QMenu>
#include <QMenuBar>
#include <QMessageBox>
#include <QPixmap>
#include <QStatusBar>
#include <QToolBar>
#include <QWhatsThis>
#include <QCloseEvent>
#include <QTextStream>
#include <QMdiArea>
#include <QMdiSubWindow>
#include <QStyle>
#include <QMetaObject>
#include <QDateTime>
#include <QPushButton>
#include <QProcess>
#include <QProgressBar>
#include <QDir>


// for TabPosition enum
#include <QTabWidget>

// application specific includes
#include <stdlib.h>
#ifndef WIN32
#include <unistd.h>
#endif

#include "dcoptions.h"
#include "dchublistmanager.h"
#include "dcconnectionmanager.h"
#include "dctransferview.h"
#include "dcconfig.h"
#include "dchubsearch.h"
#include "dcspy.h"
#include "dcuserslist.h"
#include "dctranslator.h"
#include "dcevent.h"
#include "dcpluginmanager.h"
#include "dcmenuhandler.h"
#include "dciconloader.h"
#include "dcguiutils.h"
#include "dcquickconnect.h"

#ifndef WIN32
    #include "dcinotifycontrol.h"
#endif

#include "dcclient.h"
#include "dcantispam.h"
#include "dcantispamcontrol.h"
#include "dcipfilter.h"
#include "dcipfiltercontrol.h"

#include <iostream>

#include "DCDialogAbout.h"
#include "ui/DCDialogDebugSettings.h"

#include <dclib/dcos.h>
#include <dclib/dcobject.h>
#include <dclib/cdownloadmanager.h>
#include <dclib/cfilemanager.h>
#include <dclib/csearchmanager.h>
#include <dclib/cutils.h>
#include <dclib/core/cdir.h>
#include <dclib/dclib.h>
#include <dclib/core/csocket.h>

#if defined(HAVE_CONFIG_H)
#include <config.h>
#endif

#if defined(HAVE_MALLOC_H)
#include <malloc.h>
#include <stdio.h>
#endif

DCGuiApp * g_pMainWin = NULL;
QMdiArea * g_pMdiArea = NULL;

DCChat * g_pActiveChat = NULL;

/** */
DCGuiApp::DCGuiApp()
{
	StringMap * map;
	StringMap * tabBarMap;
	int width,height;
	bool b;
	
	m_bTransferViewGotTrayed = false;
	m_bIsQuitPromptVisible = false;
	
	setWindowTitle( tr("EiskaltDC") + QString(" ") + QString(PACKAGE_VERSION) );

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

	SetTheme();

	///////////////////////////////////////////////////////////////////
	// call inits to invoke all other construction parts
	initView();
	initActions();
	initMenuBar();
	initToolBar();
	initStatusBar();
	initTray();

	connect( g_pConfig, SIGNAL(defaultDownloadModeChanged()), this, SLOT(slotDefaultDownloadModeChanged()) );
	connect( g_pConfig, SIGNAL(awayModeChanged( eUserAwayMode )), this, SLOT(slotAwayModeChanged( eUserAwayMode )) );
	connect( g_pConfig, SIGNAL(autoAwayModeChanged( bool )), this, SLOT(slotAutoAwayModeChanged( bool )) );

	if ( !(g_pConfig->GetBackgroundPixmap().isEmpty()) )
	{
		QPixmap bp;
		if ( bp.load(g_pConfig->GetBackgroundPixmap()) )
			pMdiArea->setBackground(bp);
	}

	g_pConfig->GetAppGeometry( width, height );
	resize( width, height );

	b = true;

	// init transferview
	if ( g_pConfig->GetMap("TRANSFERVIEW",map) )
	{
		if ( (*map)["DOCKED"].toInt() == 0 )
		{
			b = false;
		}
	}

	if ( b )
	{
		pTransferViewDock->setFloating(false);

		if ( ((*map)["HEIGHT"].toInt() != 0) &&
		     ((*map)["WIDTH"].toInt() != 0) )
		{
			//pTransferViewDock->setFixedExtentHeight((*map)["HEIGHT"].toInt());
			//pTransferViewDock->setFixedExtentWidth((*map)["WIDTH"].toInt());
		}
		
		bool nl = true;
		if ( (*map)["NL"] == "FALSE" )
		{
			nl = false;
		}
		//moveDockWindow( pTransferViewDock, Qt::Dock((*map)["DOCK"].toInt()), nl, (*map)["INDEX"].toInt(), (*map)["EXTRAOFFSET"].toInt() );
	}
	else
	{
		pTransferViewDock->setFloating(true);

		if ( ((*map)["HEIGHT"].toInt() != 0) &&
		     ((*map)["WIDTH"].toInt() != 0) )
		{
			pTransferViewDock->resize( (*map)["WIDTH"].toInt(), (*map)["HEIGHT"].toInt() );
		}
	}

	viewTabBar->setChecked(true);
	viewToolBar->setChecked(true);
	viewStatusBar->setChecked(true);
	
	m_bWasMaximized = false;

	// init main window
	if ( g_pConfig->GetMap("MAINVIEW",map) )
	{
		if ( (*map)["MAXIMIZED"].toInt() == 1 )
		{
			m_bWasMaximized = true;
		}
		else
		{
			m_bWasMaximized = false;
		}

		if ( (*map)["DOCKED"].toInt() == 0 )
		{
			//fileToolbar->setFloating(true);
		}
		else
		{
			//fileToolbar->setFloating(false);

			//moveDockWindow( fileToolbar, Qt::Dock((*map)["DOCK"].toInt()) );
		}
	}

	if ( g_pConfig->GetTabBar() == false )
		viewTabBar->toggle();
	if ( g_pConfig->GetToolBar() == false )
		viewToolBar->toggle();
        if ( g_pConfig->GetStatusBar() == false )
                viewStatusBar->toggle();
	if ( g_pConfig->GetShowTransferWin() )
	{
            switch (g_pConfig->GetTransferViewType()){
                case etvtDOCK:
                    pTransferViewDock->setWidget(g_pTransferView);
                    pTransferViewDock->show();

                    break;
                case etvtWINDOW:
                    g_pTransferView->initContainer();

                    showMDIWidget(g_pTransferView->GetContainer());
                    connect(g_pTransferView, SIGNAL(onDie(QWidget*)), this, SLOT(slotChildOnDie(QWidget*)));

                    g_pConnectionManager->addTab(g_pTransferView, QApplication::translate("DCDialogTransfer", "Transfer List", 0, QApplication::UnicodeUTF8));

                    break;
            }
	}

	// restore tabbar position and state
	if ( g_pConfig->GetMap("TABBAR",tabBarMap) )
	{
		int x = (*tabBarMap)["X"].toInt();
		int y = (*tabBarMap)["Y"].toInt();
		int w = (*tabBarMap)["WIDTH"].toInt();
		int h = (*tabBarMap)["HEIGHT"].toInt();
		
		if ( (*tabBarMap)["DOCKED"].toInt() == 0 )
		{
			//windowsTabBar->setFloating(true);
			
			if ( (w != 0) && (h != 0) )
			{
				windowsTabBar->resize(w,h);
			}
		
			windowsTabBar->move(x,y);
		}
		else
		{
			//windowsTabBar->setFloating(false);
			
			bool nl = true;
			if ( (*tabBarMap)["NL"] == "FALSE" )
			{
				nl = false;
			}
			
			//moveDockWindow( windowsTabBar, Qt::Dock((*tabBarMap)["DOCK"].toInt()), nl, (*tabBarMap)["INDEX"].toInt(), (*tabBarMap)["EXTRAOFFSET"].toInt() );
			
			/* if ( (w != 0) && (h != 0) )
			{
				windowsTabBar->setFixedExtentWidth(w);
				windowsTabBar->setFixedExtentHeight(h);
			} */
		}
	}

	restoreState(g_pConfig->GetQMainWindowState());
	
	new DCTranslator( this );

	// install event filter on qApp ;-)
	if ( g_pConfig->GetAutoAwayMode() )
	{
		qApp->installEventFilter(&m_ApplicationEvents);
	}

	// init timer
	m_pTimer = new QTimer();

	connect( m_pTimer, SIGNAL(timeout()), this, SLOT(slotTimeout()) );

	// start timer
	m_pTimer->start( 1000 );
	
	g_pMainWin = this;
        g_pMdiArea = pMdiArea;

        ready2Unload = false;

        slotFileInotifyEnable();

        if (g_pConfig->GetAntiSpamEnabled()){
            new DCAntiSpam();

            g_pAntiSpam->loadSettings();
            g_pAntiSpam->loadLists();
        }

	if (g_pConfig->GetIPFilterEnabled()){
	    new DCIPFilter();

	    g_pIPFilter->loadList();
	}
}

/** */
DCGuiApp::~DCGuiApp()
{
	g_pMainWin = NULL;
	
	deinitActions();

	// remove event-filter from appl.
	if ( g_pConfig->GetAutoAwayMode() )
	{
		qApp->removeEventFilter(&m_ApplicationEvents);
	}

	// stop timer
	m_pTimer->stop();
	delete m_pTimer;

	deinitTray();

	deinitView();

	delete g_pTranslator;

        if (g_pAntiSpam){

            g_pAntiSpam->saveLists();
            g_pAntiSpam->saveSettings();

            delete g_pAntiSpam;
        }
}

/** */
void DCGuiApp::initActions()
{
        actionClearChat = new QAction(this);
        actionClearChat->setText(tr("Clear Current chat"));
        actionClearChat->setStatusTip(tr("Clear Current chat"));
        actionClearChat->setIcon(QIcon(g_pIconLoader->GetPixmap(eiCLEAR)));
        actionClearChat->setShortcut(tr("Ctrl+R"));
        connect(actionClearChat, SIGNAL(triggered()), this, SLOT(slotClearCurrentChat()));

	QIcon optionsIcon( g_pIconLoader->GetPixmap(eiCONFIGURE_32x32) );
	optionsIcon.addPixmap( g_pIconLoader->GetPixmap(eiCONFIGURE) );
	fileOptions = new QAction(this);
	fileOptions->setText(tr("&Options"));
	fileOptions->setIcon(optionsIcon);
	fileOptions->setShortcut(tr("Ctrl+O"));
	fileOptions->setStatusTip(tr("Open options dialog"));
	fileOptions->setWhatsThis(tr("Open options dialog\n\nOpens a dialog where settings can be changed."));
	connect(fileOptions, SIGNAL(triggered()), this, SLOT(slotFileOptions()));

        fileQuickConnect = new QAction(this);
        fileQuickConnect->setText(tr("&Quick connect"));
        fileQuickConnect->setIcon( QIcon( g_pIconLoader->GetPixmap(eiCONNECT) ) );
        fileQuickConnect->setStatusTip(tr("Open quick-connect dialog"));
        fileQuickConnect->setShortcut(tr("Ctrl+H"));
        connect(fileQuickConnect, SIGNAL(triggered()), this, SLOT(slotFileQuickConnect()));

#ifndef WIN32
        fileInotifyEnable = new QAction(this);
        fileInotifyEnable->setText(tr("Inotify enabled"));
        fileInotifyEnable->setStatusTip(tr("Enables INotify support"));
        fileInotifyEnable->setCheckable(true);
        fileInotifyEnable->setChecked(g_pConfig->GetInotifyEnabled());
        connect(fileInotifyEnable, SIGNAL(triggered()), this, SLOT(slotFileInotifyEnable()));

        fileInotify = new QAction(this);
        fileInotify->setText(tr("&Inotify control"));
        fileInotify->setIcon( QIcon( g_pIconLoader->GetPixmap(eiINOTIFY) ) );
        fileInotify->setEnabled(g_pConfig->GetInotifyEnabled());
        connect(fileInotify, SIGNAL(triggered()), this, SLOT(slotInotify()));
#endif

	fileFileListBrowser = new QAction(this);
	fileFileListBrowser->setText(tr("Filelist browser"));
	fileFileListBrowser->setIcon( QIcon( g_pIconLoader->GetPixmap(eiVIEW_SIDETREE) ) );
	fileFileListBrowser->setStatusTip(tr("Open filelist browser"));
	fileFileListBrowser->setWhatsThis(tr("Open filelist browser\n\nOpen an empty filelist browser that you can use to open filelists from disk."));
	connect(fileFileListBrowser, SIGNAL(triggered()), this, SLOT(slotFileFileListBrowser()));

	fileFileListBrowserLocal = new QAction(this);
	fileFileListBrowserLocal->setText(tr("Filelist browser local"));
	fileFileListBrowserLocal->setIcon( QIcon( g_pIconLoader->GetPixmap(eiVIEW_SIDETREE) ) );
	fileFileListBrowserLocal->setStatusTip(tr("Open local filelist browser"));
	fileFileListBrowserLocal->setWhatsThis(tr("Open local filelist browser\n\nView the files in your own share."));
	connect(fileFileListBrowserLocal, SIGNAL(triggered()), this, SLOT(slotFileFileListBrowserLocal()));

	QIcon refreshIcon( g_pIconLoader->GetPixmap(eiRELOAD_32x32) );
	refreshIcon.addPixmap( g_pIconLoader->GetPixmap(eiRELOAD) );
	fileFileListRefresh = new QAction(this);
	fileFileListRefresh->setText(tr("Refresh share"));
	fileFileListRefresh->setIcon( refreshIcon );
	fileFileListRefresh->setStatusTip(tr("Refresh share"));
	fileFileListRefresh->setWhatsThis(tr("Refresh share\n\nUpdate your share to match file changes on disk."));
	connect( fileFileListRefresh, SIGNAL(triggered()), this, SLOT(slotFileCreateShare()) );

	fileQuickOptions = new QAction(this);
	fileQuickOptions->setText(tr("Quick options"));
	fileQuickOptions->setShortcut(tr("F12"));
	fileQuickOptions->setStatusTip(tr("Select default download mode"));
	connect(fileQuickOptions, SIGNAL(triggered()), this, SLOT(slotFileQuickOptions()));

	/** Default download mode */
	fileDefaultDldAsk = new QAction(this);
	fileDefaultDldAsk->setText(tr("Download mode: Ask"));
	fileDefaultDldAsk->setStatusTip(tr("Set default download mode to: Ask"));
	fileDefaultDldAsk->setWhatsThis(tr("Download mode: Ask\n\nPrompt for single or multi source mode when starting a download."));
	fileDefaultDldAsk->setCheckable(true);
	fileDefaultDldSingle = new QAction(this);
	fileDefaultDldSingle->setText(tr("Download mode: Single"));
	fileDefaultDldSingle->setStatusTip(tr("Set default download mode to: Single"));
	fileDefaultDldSingle->setWhatsThis(tr("Download mode: Single\n\nEach file will be downloaded from a single user without using chunked downloading."));
	fileDefaultDldSingle->setCheckable(true);
	fileDefaultDldMulti = new QAction(this);
	fileDefaultDldMulti->setText(tr("Download mode: Multi"));
	fileDefaultDldMulti->setStatusTip(tr("Set default download mode to: Multi"));
	fileDefaultDldMulti->setWhatsThis(tr("Download mode: Multi\n\nEach file will be downloaded in multiple chunks possibly from different users."));
	fileDefaultDldMulti->setCheckable(true);
	fileDefaultDldGroup = new QActionGroup( this );
        connect( fileDefaultDldGroup, SIGNAL( selected(QAction*) ), this, SLOT(slotChangeDefaultDldMode(QAction*)) );
	fileDefaultDldGroup->addAction(fileDefaultDldAsk);
	fileDefaultDldGroup->addAction(fileDefaultDldSingle);
	fileDefaultDldGroup->addAction(fileDefaultDldMulti);

	slotDefaultDownloadModeChanged();

	fileReloadPlugins = new QAction(this);
	fileReloadPlugins->setText(tr("&Reload Plugins"));
	fileReloadPlugins->setIcon( QIcon( g_pIconLoader->GetPixmap(eiRELOAD_PLUGINS) ) );
	fileReloadPlugins->setStatusTip(tr("Reload Plugins"));
	fileReloadPlugins->setWhatsThis(tr("Reload Plugins\n\nScan for new and reload any add-on software."));
	connect(fileReloadPlugins, SIGNAL(triggered()), this, SLOT(slotFileReloadPlugins()));

	fileQuit = new QAction(this);
	fileQuit->setText(tr("Exit"));
	fileQuit->setIcon( QIcon( g_pIconLoader->GetPixmap(eiEXIT) ) );
	fileQuit->setShortcut(tr("Ctrl+Q"));
	fileQuit->setStatusTip(tr("Quits the application"));
	fileQuit->setWhatsThis(tr("Exit\n\nQuits the application."));
	connect(fileQuit, SIGNAL(triggered()), this, SLOT(slotFileQuit()));

        chatZoomIn = new QAction(this);
        chatZoomIn->setText(tr("Zoom In Chat"));
        chatZoomIn->setStatusTip(tr("Zoom In Chat"));
        chatZoomIn->setIcon( QIcon(g_pIconLoader->GetPixmap(eiZOOM_IN)) );
        connect(chatZoomIn, SIGNAL(triggered()), this, SLOT(slotChatZoomIn()));

        chatZoomOut = new QAction(this);
        chatZoomOut->setText(tr("Zoom Out Chat"));
        chatZoomOut->setStatusTip(tr("Zoom Out Chat"));
        chatZoomOut->setIcon( QIcon(g_pIconLoader->GetPixmap(eiZOOM_OUT)) );
        connect(chatZoomOut, SIGNAL(triggered()), this, SLOT(slotChatZoomOut()));

        chatOff = new QAction(this);
        chatOff->setText(tr("Disable chat"));
        chatOff->setStatusTip(tr("Disable current chat"));
        chatOff->setIcon( QIcon(g_pIconLoader->GetPixmap(eiWINDOWS_CL_LISTS)) );
        chatOff->setCheckable(true);
        connect(chatOff, SIGNAL(triggered()), this, SLOT(slotChatOff()));

	viewTabBar = new QAction(this);
	viewTabBar->setText(tr("Tabbar"));
	viewTabBar->setCheckable(true);
	viewTabBar->setStatusTip(tr("Enables/disables the tabbar"));
	viewTabBar->setWhatsThis(tr("Tabbar\n\nEnables/disables the tabbar. The tabbar shows a tab for each hub window."));
	connect(viewTabBar, SIGNAL(toggled(bool)), this, SLOT(slotViewTabBar(bool)));
	
	viewToolBar = new QAction(this);
	viewToolBar->setText(tr("Tool&bar"));
	viewToolBar->setCheckable(true);
	viewToolBar->setStatusTip(tr("Enables/disables the toolbar"));
	viewToolBar->setWhatsThis(tr("Toolbar\n\nEnables/disables the toolbar."));
	connect(viewToolBar, SIGNAL(toggled(bool)), this, SLOT(slotViewToolBar(bool)));

	viewStatusBar = new QAction(this);
	viewStatusBar->setText(tr("&Statusbar"));
	viewStatusBar->setCheckable(true);
	viewStatusBar->setStatusTip(tr("Enables/disables the statusbar"));
	viewStatusBar->setWhatsThis(tr("Statusbar\n\nEnables/disables the statusbar."));
	connect(viewStatusBar, SIGNAL(toggled(bool)), this, SLOT(slotViewStatusBar(bool)));

	viewTrayIcon = new QAction(this);
	viewTrayIcon->setText(tr("System Tray Icon"));
	viewTrayIcon->setCheckable(true);
	viewTrayIcon->setStatusTip(tr("Enables/disables the system tray icon"));
	viewTrayIcon->setWhatsThis(tr("System Tray Icon\n\nAdds or removes an icon in the system tray area."));
	viewTrayIcon->setChecked(g_pConfig->GetEnableTray());
	connect( viewTrayIcon, SIGNAL(toggled(bool)), this, SLOT(slotViewTrayIcon(bool)) );
	
	viewDock = new QAction(this);
	viewDock->setText(tr("&Dock"));
	viewDock->setStatusTip(tr("Dock the application"));
	viewDock->setIcon( QIcon( g_pIconLoader->GetPixmap(eiWINDOWS_ICON) ) );
	viewDock->setWhatsThis(tr("Dock\n\nDock the application. Only the system tray icon will be visible."));
	viewDock->setEnabled(g_pConfig->GetEnableTray());
	connect(viewDock, SIGNAL(triggered()), this, SLOT(slotViewDock()));

        actionTransferViewType = new QAction(this);
        actionTransferViewType->setText( tr("Transfer View type") );
        actionTransferViewType->setIcon( QIcon( g_pIconLoader->GetPixmap(eiTRANSFER) ) );
        actionTransferViewType->setStatusTip( tr("Change transfer view type") );
        connect( actionTransferViewType, SIGNAL(triggered()), this, SLOT(slotActionTransferViewType()));
	
	windowCascade = new QAction(this);
	windowCascade->setText(tr("&Cascade"));
	windowCascade->setIcon( QIcon( g_pIconLoader->GetPixmap(eiWINDOWS_TILED) ) );
	windowCascade->setStatusTip(tr("Cascades all windows"));
	windowCascade->setWhatsThis(tr("Cascade\n\nCascades all windows."));
	connect(windowCascade, SIGNAL(triggered()), pMdiArea, SLOT(cascadeSubWindows()));

	windowTile = new QAction(this);
	windowTile->setText(tr("&Tile Vertically"));
	windowTile->setIcon( QIcon( g_pIconLoader->GetPixmap(eiWINDOWS_VERT) ) );
	windowTile->setStatusTip(tr("Tiles all windows vertically"));
	windowTile->setWhatsThis(tr("Tile Vertically\n\nTiles all windows vertically."));
	connect(windowTile, SIGNAL(triggered()), this, SLOT(tileVertically()));

	windowTileHor = new QAction(this);
	windowTileHor->setText(tr("Tile &Horizontally"));
	windowTileHor->setIcon( QIcon( g_pIconLoader->GetPixmap(eiWINDOWS_HORIZ) ) );
	windowTileHor->setStatusTip(tr("Tiles all windows horizontally."));
	windowTileHor->setWhatsThis(tr("Tile Horizontally\n\nTiles all windows horizontally."));
	connect(windowTileHor, SIGNAL(triggered()), pMdiArea, SLOT(tileSubWindows()));

	windowMinimize = new QAction(this);
	windowMinimize->setText(tr("&Minimize"));
	windowMinimize->setIcon( QIcon( g_pIconLoader->GetPixmap(eiWINDOWS_ICON) ) );
	windowMinimize->setStatusTip(tr("Minimize all windows."));
	windowMinimize->setWhatsThis(tr("Minimize\n\nMinimize all windows."));
	connect(windowMinimize, SIGNAL(triggered()), this, SLOT(slotWindowMinimize()));

	windowCloseHubs = new QAction(this);
	windowCloseHubs->setText(tr("Close disconnected hubs"));
	windowCloseHubs->setIcon( QIcon( g_pIconLoader->GetPixmap(eiWINDOWS_CL_HUBS) ) );
	windowCloseHubs->setStatusTip(tr("Close all disconnected hub windows."));
	windowCloseHubs->setWhatsThis(tr("Close disconnected hubs\n\nClose all disconnected hub windows."));
	connect(windowCloseHubs, SIGNAL(triggered()), this, SLOT(slotWindowCloseHubs()));

	windowCloseAllChats = new QAction(this);
	windowCloseAllChats->setText(tr("Close all chat windows"));
	windowCloseAllChats->setIcon( QIcon( g_pIconLoader->GetPixmap(eiWINDOWS_CL_ALL) ) );
	windowCloseAllChats->setStatusTip(tr("Close all chat windows."));
	windowCloseAllChats->setWhatsThis(tr("Close all chat windows\n\nClose all chat windows."));
	connect(windowCloseAllChats, SIGNAL(triggered()), this, SLOT(slotWindowCloseAllChats()));

	windowCloseOfflineChats = new QAction(this);
	windowCloseOfflineChats->setText(tr("Close all offline chat windows"));
	windowCloseOfflineChats->setIcon( QIcon( g_pIconLoader->GetPixmap(eiWINDOWS_CL_OFFLINE) ) );
	windowCloseOfflineChats->setStatusTip(tr("Close all offline chat windows."));
	windowCloseOfflineChats->setWhatsThis(tr("Close all offline chat windows\n\nClose all chat windows where the user is no longer on the hub."));
	connect( windowCloseOfflineChats, SIGNAL(triggered()), this, SLOT(slotWindowCloseOfflineChats()) );
	
	windowCloseFilelists = new QAction(this);
	windowCloseFilelists->setText(tr("Close all filelist windows"));
	windowCloseFilelists->setIcon( QIcon( g_pIconLoader->GetPixmap(eiWINDOWS_CL_LISTS) ) );
	windowCloseFilelists->setStatusTip(tr("Close all filelist windows."));
	windowCloseFilelists->setWhatsThis(tr("Close all filelist windows\n\nClose all filelist browsers."));
	connect( windowCloseFilelists, SIGNAL(triggered()), this, SLOT(slotWindowCloseFilelists()) );

	windowCloseSearches = new QAction(this);
	windowCloseSearches->setText(tr("Close all search windows"));
	windowCloseSearches->setIcon( QIcon( g_pIconLoader->GetPixmap(eiWINDOWS_CL_FIND) ) );
	windowCloseSearches->setStatusTip(tr("Close all search windows."));
	windowCloseSearches->setWhatsThis(tr("Close all search windows\n\nClose all search windows."));
	connect( windowCloseSearches, SIGNAL(triggered()), this, SLOT(slotWindowCloseSearches()) );

	windowAction = new QActionGroup(this);
	windowAction->addAction(windowCascade);
	windowAction->addAction(windowTile);
	windowAction->addAction(windowTileHor);
	windowAction->addAction(windowMinimize);
	windowAction->addAction(windowCloseHubs);
	windowAction->addAction(windowCloseAllChats);
	windowAction->addAction(windowCloseOfflineChats);
	windowAction->addAction(windowCloseFilelists);
	windowAction->addAction(windowCloseSearches);
	windowsGroup = new QActionGroup(this);
	connect( windowsGroup, SIGNAL(triggered(QAction*)), this, SLOT(windowMenuActivated(QAction*)) );

	/** server list */
	actionServerList = new QAction(this);
	actionServerList->setText(tr("H&ub List"));
	actionServerList->setIcon( QIcon( g_pIconLoader->GetPixmap(eiSERVER) ) );
	actionServerList->setShortcut(tr("Ctrl+U"));
	actionServerList->setStatusTip(tr("Show Hub List."));
	actionServerList->setWhatsThis(tr("Hub List\n\nShows the lists of public and bookmarks hubs."));
	connect(actionServerList, SIGNAL(triggered()), this, SLOT(slotActionServerList()));

	/** tranfer list */
	actionTransferList = new QAction(this);
	actionTransferList->setText(tr("&Transfer List"));
	actionTransferList->setIcon( QIcon( g_pIconLoader->GetPixmap(eiTRANSFER) ) );
	actionTransferList->setShortcut(tr("Ctrl+T"));
	actionTransferList->setStatusTip(tr("Show Transfer List."));
	actionTransferList->setWhatsThis(tr("Transfer List\n\nShows running transfers, users you are waiting to download from, files you have queued to download, slots granted, and log of transfers."));
	connect(actionTransferList, SIGNAL(triggered()), this, SLOT(slotActionTransferList()));

	/** hub search */
	QIcon searchIcon( g_pIconLoader->GetPixmap(eiFIND_32x32) );
	searchIcon.addPixmap( g_pIconLoader->GetPixmap(eiFIND) );
	actionHubSearch = new QAction(this);
	actionHubSearch->setText(tr("Hub &Search"));
	actionHubSearch->setIcon( searchIcon );
	actionHubSearch->setShortcut(tr("Ctrl+S"));
	actionHubSearch->setStatusTip(tr("Open Hub Search."));
	actionHubSearch->setWhatsThis(tr("Hub Search\n\nOpens a search window where you can search for files."));
	connect(actionHubSearch, SIGNAL(triggered()), this, SLOT(slotActionHubSearch()));

	/** spy */
	actionSpy = new QAction(this);
	actionSpy->setText(tr("S&py"));
	actionSpy->setIcon( QIcon( g_pIconLoader->GetPixmap(eiSPY) ) );
	actionSpy->setShortcut(tr("Ctrl+P"));
	actionSpy->setStatusTip(tr("Show Search Spy."));
	actionSpy->setWhatsThis(tr("Spy\n\nThe search spy shows incoming searches and search statistics."));
	connect(actionSpy, SIGNAL(triggered()), this, SLOT(slotActionSpy()));

	/** users */
	QIcon usersIcon( g_pIconLoader->GetPixmap(eiUSERS_32x32) );
	usersIcon.addPixmap( g_pIconLoader->GetPixmap(eiUSERS) );
	actionUsers = new QAction(this);
	actionUsers->setText(tr("Users"));
	actionUsers->setIcon( usersIcon );
	actionUsers->setShortcut(tr("Ctrl+F"));
	actionUsers->setStatusTip(tr("Show Users List."));
	actionUsers->setWhatsThis(tr("Users\n\nList of favorite users, showing if they are online."));
	connect(actionUsers, SIGNAL(triggered()), this, SLOT(slotActionUsers()));

	/** actiongroup for away mode */
	actionGroupAwayMode = new QActionGroup( this );
        actionGroupAwayMode->setExclusive( true );

	/** away mode normal */
	actionAwayModeNormal = new QAction(this);
	actionAwayModeNormal->setText(tr("&Normal"));
	actionAwayModeNormal->setCheckable(true);
	actionAwayModeNormal->setActionGroup(actionGroupAwayMode);
	actionAwayModeNormal->setShortcut(tr("Ctrl+N"));
	actionAwayModeNormal->setStatusTip(tr("Set away mode to normal"));
	actionAwayModeNormal->setWhatsThis(tr("Away mode: normal\n\nNormal mode, away message will not be sent automatically."));
	actionAwayModeNormal->setChecked(true);

	/** away mode away */
	actionAwayModeAway = new QAction(this);
	actionAwayModeAway->setText(tr("&Away"));
	actionAwayModeAway->setActionGroup(actionGroupAwayMode);
	actionAwayModeAway->setShortcut(tr("Ctrl+A"));
	actionAwayModeAway->setStatusTip(tr("Set away mode to away."));
	actionAwayModeAway->setWhatsThis(tr("Away mode: normal\n\nYou will be marked as away and your away message will be sent in response to a new private message."));
	actionAwayModeAway->setCheckable(true);

        connect( actionGroupAwayMode, SIGNAL( selected( QAction* ) ), this, SLOT( slotChangeAwayMode() ) );

        actionAntiSpam = new QAction(this);
        actionAntiSpam->setText(tr("AntiSpam Control"));
        actionAntiSpam->setIcon( QIcon( g_pIconLoader->GetPixmap(eiSPAM) ) );
        actionAntiSpam->setStatusTip(tr("Show AntiSpam control dialog"));
        connect(actionAntiSpam, SIGNAL(triggered()), this, SLOT(slotActionAntiSpam()));

	actionIPFilter = new QAction(this);
	actionIPFilter->setText(tr("IPFilter Control"));
	actionIPFilter->setIcon(QIcon( g_pIconLoader->GetPixmap(eiFILTER) ));
	actionIPFilter->setStatusTip(tr("Show IPFilter control dialog"));
	connect(actionIPFilter, SIGNAL(triggered()), this, SLOT(slotActionIPFilter()));

	helpAboutApp = new QAction(this);
	helpAboutApp->setText(tr("&About..."));
	helpAboutApp->setIcon( QIcon( g_pIconLoader->GetPixmap(eiICON_22x22) ) );
	helpAboutApp->setStatusTip(tr("About the application."));
	helpAboutApp->setWhatsThis(tr("About\n\nAbout the application. Displays version, copyright and licensing information."));
	connect(helpAboutApp, SIGNAL(triggered()), this, SLOT(slotHelpAbout()));

	helpManualApp = new QAction(this);
	helpManualApp->setText(tr("&Manual..."));
	helpManualApp->setIcon( QIcon( g_pIconLoader->GetPixmap(eiONLINEMANUAL) ) );
	helpManualApp->setStatusTip(tr("Online User Manual."));
	helpManualApp->setWhatsThis(tr("Manual\n\nOnline User Manual. Launches the configured web browser."));
	connect(helpManualApp, SIGNAL(triggered()), this, SLOT(slotHelpManual()));

	helpSupportApp = new QAction(this);
	helpSupportApp->setText(tr("&Support..."));
	helpSupportApp->setIcon( QIcon( g_pIconLoader->GetPixmap(eiSUPPORT) ) );
	helpSupportApp->setStatusTip(tr("Connect to Valknut hub"));
	helpSupportApp->setWhatsThis(tr("Support\n\nConnect to the Valknut hub."));
	connect(helpSupportApp, SIGNAL(triggered()), this, SLOT(slotHelpSupport()));

	debugSettings = new QAction(this);
	debugSettings->setText(tr("Debug Settings..."));
	debugSettings->setIcon( QIcon( g_pIconLoader->GetPixmap(eiDEBUG) ) );
	debugSettings->setStatusTip(tr("Settings for debugging"));
	debugSettings->setWhatsThis(tr("Debug Settings\n\nChange settings useful for debugging."));
	connect( debugSettings, SIGNAL(triggered()), this, SLOT(slotDebugSettings()) );
}

/** */
void DCGuiApp::deinitActions()
{
	delete fileOptions;
	delete fileFileListBrowser;
	delete fileFileListBrowserLocal;
	delete fileFileListRefresh;
	delete fileQuickOptions;
	delete fileDefaultDldAsk;
	delete fileDefaultDldSingle;
	delete fileDefaultDldMulti;
	delete fileDefaultDldGroup;
	delete fileReloadPlugins;
	delete fileQuit;
        delete fileInotify;
        delete fileInotifyEnable;
        delete actionClearChat;

	delete viewTabBar;
	delete viewToolBar;
	delete viewStatusBar;
	delete viewTrayIcon;
	delete viewDock;

	delete windowCascade;
	delete windowTile;
	delete windowTileHor;
	delete windowMinimize;
	delete windowCloseHubs;
	delete windowCloseAllChats;
	delete windowCloseOfflineChats;
	delete windowCloseFilelists;
	delete windowCloseSearches;
	delete windowAction;
	delete windowsGroup;

	delete actionServerList;
	delete actionTransferList;
	delete actionHubSearch;
	delete actionSpy;
	delete actionUsers;
	delete actionAwayModeNormal;
	delete actionAwayModeAway;
	delete actionGroupAwayMode;

	delete helpAboutApp;
	delete helpManualApp;
	delete helpSupportApp;
	
	delete debugSettings;
}

/** */
void DCGuiApp::initMenuBar()
{
	///////////////////////////////////////////////////////////////////
	// MENUBAR

	///////////////////////////////////////////////////////////////////
	// menuBar entry pFileMenu
	pFileMenu=new QMenu(this);
	pFileMenu->setTitle(tr("&File"));
	pFileMenu->addAction(fileOptions);
	pQuickOptionsMenu=new QMenu(this);
	pQuickOptionsMenu->addActions(fileDefaultDldGroup->actions());
	pQuickOptionsMenu->setTitle(tr("Quick Options"));
	pQuickOptionsMenu->setIcon( QIcon( g_pIconLoader->GetPixmap(eiQUICKOPTIONS) ) );
#ifndef WIN32
        pInotify = new QMenu(this);
        pInotify->setTitle(tr("INotify"));
        pInotify->setIcon( QIcon( g_pIconLoader->GetPixmap(eiINOTIFY) ) );
        pInotify->addAction(fileInotifyEnable);
        pInotify->addSeparator();
        pInotify->addAction(fileInotify);
#endif

        pQuickOptionsMenu->addMenu(pInotify);
	pFileMenu->addMenu(pQuickOptionsMenu);
	pFileMenu->addSeparator();
	pFileMenu->addAction(fileFileListBrowser);
	pFileMenu->addAction(fileFileListBrowserLocal);
#ifndef WIN32
        pFileMenu->addAction(fileInotify);
#endif
        pFileMenu->addSeparator();
        pFileMenu->addAction(fileQuickConnect);
	pFileMenu->addSeparator();
	pFileMenu->addAction(fileFileListRefresh);
	pFileMenu->addSeparator();
	pFileMenu->addAction(fileReloadPlugins);
        pFileMenu->addSeparator();
        pFileMenu->addAction(actionClearChat);
	pFileMenu->addSeparator();
	pFileMenu->addAction(fileQuit);

	///////////////////////////////////////////////////////////////////
	// menuBar entry viewMenu
	pViewMenu=new QMenu(this);
	
	pViewMenu->setTitle(tr("&View"));
	pViewMenu->addAction(viewTabBar);
	pViewMenu->addAction(viewToolBar);
	pViewMenu->addAction(viewStatusBar);
	pViewMenu->addAction(viewTrayIcon);
	pViewMenu->addAction(viewDock);
        pViewMenu->addSeparator();
	pViewMenu->addAction(actionTransferViewType);

	///////////////////////////////////////////////////////////////////
	// menuBar awayMenu
	pAwayMenu=new QMenu(this);
	pAwayMenu->setTitle(tr("Away &Mode"));
	pAwayMenu->setIcon( QIcon( g_pIconLoader->GetPixmap(eiISAWAY) ) );
	pAwayMenu->addAction(actionAwayModeNormal);
	pAwayMenu->addAction(actionAwayModeAway);

	///////////////////////////////////////////////////////////////////
	// menuBar actionMenu
	pActionMenu=new QMenu(this);
	pActionMenu->setTitle(tr("&Action"));
	pActionMenu->addAction(actionServerList);
	pActionMenu->addAction(actionTransferList);
	pActionMenu->addAction(actionHubSearch);
	pActionMenu->addAction(actionSpy);
	pActionMenu->addAction(actionUsers);
	pActionMenu->addSeparator();
	pActionMenu->addMenu(pAwayMenu);
        pActionMenu->addSeparator();
        pActionMenu->addAction(actionAntiSpam);
	pActionMenu->addAction(actionIPFilter);

	///////////////////////////////////////////////////////////////////
	// menuBar entry windowMenu
	pWindowMenu = new QMenu(this);
	pWindowMenu->setTitle(tr("&Window"));
	connect(pWindowMenu, SIGNAL(aboutToShow()), this, SLOT(windowMenuAboutToShow()));

	///////////////////////////////////////////////////////////////////
	// menuBar entry helpMenu
	pHelpMenu=new QMenu(this);
	pHelpMenu->setTitle(tr("&Help"));
	pHelpMenu->addAction(helpAboutApp);
	pHelpMenu->addSeparator();
	pHelpMenu->addAction(helpManualApp);
	pHelpMenu->addSeparator();
	pHelpMenu->addAction(helpSupportApp);
	pHelpMenu->addSeparator();
	pHelpMenu->addAction(debugSettings);
	pHelpMenu->addSeparator();
	pHelpMenu->addAction(QWhatsThis::createAction(pHelpMenu));

	menuBar()->addMenu(pFileMenu);
	menuBar()->addMenu(pViewMenu);
	menuBar()->addMenu(pActionMenu);
	menuBar()->addMenu(pWindowMenu);
	menuBar()->addMenu(pHelpMenu);
}

/** */
void DCGuiApp::initToolBar()
{
	///////////////////////////////////////////////////////////////////
	// TOOLBAR
	fileToolbar = new QToolBar(this);
	fileToolbar->setObjectName("FileToolBar");
	fileToolbar->setWindowTitle(tr("Toolbar"));

        fileToolbar->addAction(fileQuickConnect);
        fileToolbar->addAction(fileFileListRefresh);
	fileToolbar->addAction(fileOptions);
	fileToolbar->addSeparator();
	fileToolbar->addAction(actionServerList);
	fileToolbar->addAction(actionHubSearch);
	fileToolbar->addAction(actionTransferList);
	fileToolbar->addAction(actionSpy);
	fileToolbar->addAction(actionUsers);
        fileToolbar->addAction(actionAntiSpam);
        fileToolbar->addSeparator();
        fileToolbar->addAction(chatZoomOut);
        fileToolbar->addAction(chatZoomIn);
        fileToolbar->addAction(actionClearChat);
        fileToolbar->addAction(chatOff);
	fileToolbar->addSeparator();
        fileToolbar->addAction(fileQuit);

	// ADD USERS HERE
	fileToolbar->addSeparator();
	addToolBar(Qt::TopToolBarArea, fileToolbar);
	
	windowsTabBar = new QToolBar(this);
	windowsTabBar->setWindowTitle(tr("Tab Bar"));
	windowsTabBar->setObjectName("ClientsTabBar");
	addToolBar(Qt::TopToolBarArea, windowsTabBar);
	
	// init tabbar
	g_pConnectionManager->InitTabBar(windowsTabBar);
}

/** */
void DCGuiApp::initStatusBar()
{
	///////////////////////////////////////////////////////////////////
	//STATUSBAR
	statusBar()->showMessage(tr("Ready."));

	statusDMLabel = new QLabel(statusBar());
	statusDMLabel->setObjectName("DownloadManagerStatusLabel");
	statusDMLabel->setFrameShape( QFrame::NoFrame );
	statusDMLabel->setFrameShadow( QFrame::Plain );

	statusDMLabel->setToolTip( tr("SL: Slots:\tUsual slots: used/maximum\n\tExtra slots: used/maximum\n\tAdditional slots: operator/user/special\nUL: Upload speed\nDL: Download speed") );

	statusBar()->addPermanentWidget(statusDMLabel);

	statusTRLabel = new QLabel(statusBar());
	statusTRLabel->setObjectName("TransferStatusLabel");
	statusTRLabel->setFrameShape( QFrame::NoFrame );
	statusTRLabel->setFrameShadow( QFrame::Plain );
	statusBar()->addPermanentWidget(statusTRLabel);
	statusTRLabel->setToolTip( tr("RX/TX Traffic.") );

	statusDSLabel = new QLabel(statusBar());
	statusDSLabel->setObjectName("DiscSpaceStatusLabel");
	statusDSLabel->setFrameShape( QFrame::NoFrame );
	statusDSLabel->setFrameShadow( QFrame::Plain );
	statusBar()->addPermanentWidget(statusDSLabel);
	statusDSLabel->setToolTip( tr("Available disc space.") );

        m_pProgessBar = new QProgressBar( statusBar() );
        m_pProgessBar->setMinimumWidth(180);
        m_pProgessBar->setMaximumWidth(180);
        m_pProgessBar->setMaximumHeight(18);
        m_pProgessBar->setMaximum(100);
        m_pProgessBar->setMinimum(0);
        m_pProgessBar->hide();
        //bar->setFormat("");
        statusBar()->addPermanentWidget(m_pProgessBar);

	statusTRLabel->setContextMenuPolicy( Qt::CustomContextMenu );
	connect( statusTRLabel, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(slotContextMenuTraffic(const QPoint &)) );
}

/** */
void DCGuiApp::initView()
{
	pMdiArea = new QMdiArea( this );

//if QT_VERSION >= 0x040400
//	pMdiArea->setActivationOrder( QMdiArea::StackingOrder );
//endif
	
	/*
	 * this is so you can compile with QT 4.3 but if you run with QT 4.4
	 * the property still gets set
	 */
	if ( pMdiArea->property("activationOrder").isValid() )
	{
		pMdiArea->setProperty("activationOrder",QMdiArea::StackingOrder);
	}

	setCentralWidget(pMdiArea);
	pMdiArea->showMaximized();
	
	// create connection manager view
	CConnectionManager::SetInstance(new DCConnectionManager(pMdiArea));

	// create hublist manager view
	CHubListManager::SetInstance(new DCHubListManager(pMdiArea));
	g_pHubListManager->GetMdiSubWindow()->hide();
	g_pHubListManager->hide();
	
	// create dock window for transfer view
        pTransferViewDock = new QDockWidget( pMdiArea );
        pTransferViewDock->setWindowTitle(tr(""));
	pTransferViewDock->setObjectName("TransferViewDock");
        pTransferViewDock->setTitleBarWidget(0);
	//pTransferViewDock->setResizeEnabled(true);
        //pTransferViewDock->setFeatures(QDockWidget::DockWidgetVerticalTitleBar);

        if (g_pConfig->GetTransferViewType() == etvtDOCK)
            addDockWidget(Qt::BottomDockWidgetArea, pTransferViewDock);

	pTransferViewDock->hide();
	//connect( pTransferViewDock, SIGNAL(placeChanged( Q3DockWindow::Place )), this, SLOT(slotTransferViewDockPlaceChanged( Q3DockWindow::Place )) );

	// create transfer view
	CDownloadManager::SetInstance(new DCTransferView(pTransferViewDock));

        //pTransferViewDock->setWidget(g_pTransferView);

	// create spy view
	new DCSpy(pMdiArea);
	g_pSpy->GetMdiSubWindow()->hide();
	g_pSpy->hide();

	// create users view
	new DCUsersList(pMdiArea);
	g_pUsersList->GetMdiSubWindow()->hide();
	g_pUsersList->hide();

/*	if ( g_pConfig->GetMode() == ecmACTIVE )
	{
		CString error;
		if ( g_pTransferView->DLM_InitListen(error) == false )
		{
			QString s;
			s = error.Data();

			if ( s.isEmpty() )
				s = tr("(no error message from socket)");
			else
				s = "(" + s + ")";

			QMessageBox::critical( 0, "Valknut",
			tr("TCP listen failed, change to passive mode! ") + s );

			g_pConfig->SetMode(ecmPASSIVE);
		}
	}
	*/
}

/** */
void DCGuiApp::deinitView()
{

	if ( g_pTransferView )
	{
		delete g_pTransferView;
	}
	
	if ( pTransferViewDock )
	{
		eTransferViewType type = g_pConfig->GetTransferViewType();

		switch (type){
		    case etvtDOCK:
			removeDockWidget(pTransferViewDock);

			break;
		    case etvtWINDOW:
			break;
		}

		delete pTransferViewDock;

		pTransferViewDock = 0;
	}

	g_pConnectionManager->CloseAllTabs();
	
	if ( g_pHubListManager )
	{
		delete g_pHubListManager;
	}
	
	if ( g_pSpy )
	{
		delete g_pSpy;
	}
	
	if ( g_pUsersList )
	{
		delete g_pUsersList;
	}
	
	if ( g_pConnectionManager )
	{
		delete g_pConnectionManager;
	}
}

/** setup all windows */
void DCGuiApp::initWindows()
{
	////////////////////////////////////////////////////////////////////
	StringMap * map;

	// setup hubview
	g_pConfig->GetMap("HUBVIEW",map);

	if ( (*map)["VISIBLE"].toInt() == 1 )
	{
		const QPoint oldpos = g_pHubListManager->GetMdiSubWindow()->pos();
                slotActionServerList();
		g_pHubListManager->GetMdiSubWindow()->move(oldpos);
		
		if ( (*map)["MAXIMIZED"].toInt() == 1 )
		{
			g_pHubListManager->GetMdiSubWindow()->showMaximized();
			g_pHubListManager->showMaximized();
		}
		else if ( (*map)["MINIMIZED"].toInt() == 1 )
		{
			g_pHubListManager->GetMdiSubWindow()->showMinimized();
			g_pHubListManager->showMinimized();
		}
		else
		{
			g_pHubListManager->GetMdiSubWindow()->show();
			g_pHubListManager->show();
		}
	}

	// setup spyview
	g_pConfig->GetMap("SPYVIEW",map);

	if ( (*map)["VISIBLE"].toInt() == 1 )
	{
		const QPoint oldpos = g_pSpy->GetMdiSubWindow()->pos();
                slotActionSpy();
		g_pSpy->GetMdiSubWindow()->move(oldpos);
		
		if ( (*map)["MAXIMIZED"].toInt() == 1 )
		{
			g_pSpy->GetMdiSubWindow()->showMaximized();
			g_pSpy->showMaximized();
		}
		else if ( (*map)["MINIMIZED"].toInt() == 1 )
		{
			g_pSpy->GetMdiSubWindow()->showMinimized();
			g_pSpy->showMinimized();
		}
		else
		{
			g_pSpy->GetMdiSubWindow()->show();
			g_pSpy->show();
		}	
	}

	// setup userview
	g_pConfig->GetMap("USERVIEW",map);

	if ( (*map)["VISIBLE"].toInt() == 1 )
	{
		const QPoint oldpos = g_pUsersList->GetMdiSubWindow()->pos();
                slotActionUsers();
		g_pUsersList->GetMdiSubWindow()->move(oldpos);

		if ( (*map)["MAXIMIZED"].toInt() == 1 )
		{
			g_pUsersList->GetMdiSubWindow()->showMaximized();
			g_pUsersList->showMaximized();
		}
		else if ( (*map)["MINIMIZED"].toInt() == 1 )
		{
			g_pUsersList->GetMdiSubWindow()->showMinimized();
			g_pUsersList->showMinimized();
		}
		else
		{
			g_pUsersList->GetMdiSubWindow()->show();
			g_pUsersList->show();
		}
	}
}

/** initialize the tray icon */
void DCGuiApp::initTray()
{
	m_pTrayIcon = 0;
	m_bTray	= false;

	if ( g_pConfig->GetEnableTray() )
	{
		m_bEnableTray = true;
		
		m_pTrayIcon = new QSystemTrayIcon();
		m_pTrayIcon->setIcon( g_pIconLoader->GetPixmap(eiICON_22x22) );

		QMenu * traymenu = new QMenu(this);
		
		traymenu->setTitle("EiskaltDC");
		
		QAction * title = traymenu->addAction("EiskaltDC");
		title->setEnabled(false);
		
		traymenu->addSeparator();
		
		QAction * dock = traymenu->addAction(tr("Dock/Undock"));
		connect( dock, SIGNAL(triggered(bool)), this, SLOT(slotViewDock()) );
		
		QAction * remove = traymenu->addAction(tr("Remove tray icon"));
		connect ( remove, SIGNAL(triggered(bool)), this, SLOT(slotRemoveTrayIcon()) );
		
		QAction * exit = traymenu->addAction(g_pIconLoader->GetPixmap(eiEXIT), tr("Exit"));
		connect( exit, SIGNAL(triggered(bool)), this, SLOT(slotFileQuit()) );
		
		m_pTrayIcon->setContextMenu(traymenu);
		
		connect( m_pTrayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(slotTrayMenuTriggered(QSystemTrayIcon::ActivationReason)) );
		
		m_pTrayIcon->show();
	}
	else
	{
		m_bEnableTray = false;
	}
}

/** deinitialize the tray icon */
void DCGuiApp::deinitTray()
{
	if ( m_pTrayIcon )
	{
		disconnect( m_pTrayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(slotTrayMenuTriggered(QSystemTrayIcon::ActivationReason)) );
		
		delete m_pTrayIcon->contextMenu();
		m_pTrayIcon->hide();
		delete m_pTrayIcon;
		m_pTrayIcon = 0;
		
		m_bEnableTray = false;
	}
}

/** */
bool DCGuiApp::queryExit()
{
	if ( m_bIsQuitPromptVisible == false )
	{
		show();
		raise();
		m_bTray = false;
		m_bIsQuitPromptVisible = true;
		int exit = QMessageBox::question(this, tr("Quit..."),
				tr("Do you really want to quit?"),
				QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Cancel);
		m_bIsQuitPromptVisible = false;
	
		return (exit==QMessageBox::Ok);
	}
	else
	{
		// never get here, m_bIsQuitPromptVisible is checked at event processing
		printf("Already asking to quit.\n");
		return false;
	}
}

/** */
void DCGuiApp::slotTimeout()
{
	if ( g_pConfig->GetAutoAwayMode() )
	{
		// check for user input
		if ( m_ApplicationEvents.m_nNoUserInputTimer == 0 )
		{
			// check away mode and reset to normal
			if ( g_pConfig->GetAwayMode() != euamNORMAL )
			{
				actionAwayModeNormal->setChecked(true);
				g_pConfig->CConfig::SetAwayMode( euamNORMAL );
			}

			m_ApplicationEvents.m_nNoUserInputTimer = time(0);
		}
		else
		{
			// away timeout
			if ( (time(0)-m_ApplicationEvents.m_nNoUserInputTimer) >= g_pConfig->GetAutoAwayTime() )
			{
				// check away mode
				if ( g_pConfig->GetAwayMode() == euamNORMAL )
				{
					actionAwayModeAway->setChecked(true);
					g_pConfig->CConfig::SetAwayMode( euamAWAY );
				}

				m_ApplicationEvents.m_nNoUserInputTimer = time(0);
			}
		}
	}

	showFreeDiscSpace();
}

/** */
void DCGuiApp::showFreeDiscSpace()
{
	CString s = g_pConfig->GetDownloadFolder();
	ulonglong n = 0;
	
	if ( s.NotEmpty() )
	{
		if ( CDir::FreeDiscSpace( s, &n ) == false )
		{
			n = 0;
		}
	}
	
	statusDSLabel->setText(DCGuiUtils::GetSizeString(n));
}

/** */
void DCGuiApp::customEvent( QEvent * event )
{
	if ( event->type() == EVENT_UPDATE_DM_STATUSBAR )
	{
		DC_DownloadManagerEvent * e = (DC_DownloadManagerEvent*)event;

		QString s = "SL: ";
		s += QString().setNum(e->m_pDownloadManagerInfo->slot_use_settings);
		s += '/';
		s += QString().setNum(e->m_pDownloadManagerInfo->slot_max);
		s += ' ';
		s += QString().setNum(e->m_pDownloadManagerInfo->slot_use_rate_extra);
		s += '/';
		if ( g_pConfig->GetExtraSlotsRate() > 0 )
		{
			s += QString().setNum(g_pConfig->GetMaxExtraSlots());
		}
		else
		{
			s += '0';
		}
		s += ' ';
		s += QString().setNum(e->m_pDownloadManagerInfo->slot_use_operator);
		s += '/';
		s += QString().setNum(e->m_pDownloadManagerInfo->slot_use_user);
		s += '/';
		s += QString().setNum(e->m_pDownloadManagerInfo->slot_use_special);

		s += " UL: ";
		s += QString::fromAscii(CUtils::GetTransferString(e->m_pDownloadManagerInfo->Rate()).Data());
		s += " DL: ";
		s += QString::fromAscii(CUtils::GetTransferString(e->m_pDownloadManagerInfo->rate_dl).Data());

		statusDMLabel->setText(s);

		// set trayicon tooltip
		if ( m_pTrayIcon )
		{
			QString tt = tr("Connected to ");
			tt += QString().setNum(g_pConnectionManager->GetConnectedHubCount());
			tt += tr(" hubs");
			tt += '\n';
			tt += s;
			tt += '\n';
			tt += statusTRLabel->text();
			m_pTrayIcon->setToolTip( tt );
		}
		
		event->accept();
	}
	else if ( event->type() == EVENT_UPDATE_FM_STATUSBAR )
	{
		DC_FileManagerEvent * e = (DC_FileManagerEvent*)event;

                bool s = false;

		switch(e->m_pFileManagerInfo->m_eFileManagerStatus)
		{
			case efmsCREATESHARELIST:
                                s = true;
                                m_pProgessBar->setFormat(tr("Share List") + " %p%");
				break;
			case efmsCREATESEARCHINDEX:
                                m_pProgessBar->setFormat(tr("Search Index") + " %p%");
                                s = true;
				break;
			case efmsCREATEHASHLIST:
                                m_pProgessBar->setFormat(tr("Hash List") + " %p%");
                                s = true;
				break;
			case efmsNONE:
                                //statusFMLabel->hide();
                                m_pProgessBar->hide();
				statusBar()->showMessage(tr("Refresh share finished."));
				break;
			default:
				break;
		}
		
                if ( s )
		{
                        //s += QString().setNum(e->m_pFileManagerInfo->m_nProgress,'f',2);
                        //s += "%";
                        //statusFMLabel->setText(s);
                        m_pProgessBar->setValue((int)e->m_pFileManagerInfo->m_nProgress);
                        m_pProgessBar->show();
		}

		event->accept();
	}
	else if ( event->type() == EVENT_UPDATE_TR_STATUSBAR )
	{
		DC_TrafficInfoEvent * e = (DC_TrafficInfoEvent*)event;

		QString s = "RX: ";
		s += DCGuiUtils::GetSizeString(e->m_pTrafficInfo->m_nRx);
		s += " TX: ";
		s += DCGuiUtils::GetSizeString(e->m_pTrafficInfo->m_nTx);

		statusTRLabel->setText(s);

		// set trayicon tooltip
		if ( m_pTrayIcon )
		{
			QString tt = tr("Connected to ");
			tt += QString().setNum(g_pConnectionManager->GetConnectedHubCount());
			tt += tr(" hubs");
			tt += '\n';
			tt += statusDMLabel->text();
			tt += '\n';
			tt += s;
			m_pTrayIcon->setToolTip( tt );
		}
		
		event->accept();
	}
	else
	{
		event->ignore();
	}
}

/** */
void DCGuiApp::closeEvent( QCloseEvent * event )
{
        if ( !ready2Unload )
        {
                event->ignore();
                slotViewDock();
        }
        else
        {
                event->accept();
        }
}

/** */
void DCGuiApp::showEvent(QShowEvent *e)
{
    e->accept();

    if (isVisible() && g_pConnectionManager)
        g_pConnectionManager->repaintTabbarIcons();
}

/////////////////////////////////////////////////////////////////////
// SLOT IMPLEMENTATION
/////////////////////////////////////////////////////////////////////

/** */
void DCGuiApp::tileVertically()
{
	int i,count =0;
	int y = 0;
	int heightForEach;

	// primitive horizontal tiling
	QList<QMdiSubWindow*> windows = pMdiArea->subWindowList();
	if ( windows.count() == 0 )
	{
		return;
	}

	for ( i = 0; i < windows.count(); i++ )
	{
		if ( windows.at(i)->isEnabled() )
			count++;
	}

	if ( count > 0 )
	{
		heightForEach = pMdiArea->height() / count;

		for ( i = 0; i < windows.count(); i++ )
		{
			if ( !windows.at(i)->isEnabled() )
				continue;
			QMdiSubWindow * window = windows.at(i);
			if ( (window->isMaximized()) || (window->isMinimized()))
			{
				// prevent flicker
				window->hide();
				window->showNormal();
			}

			int preferredHeight = window->minimumHeight()+window->parentWidget()->baseSize().height();
			int actHeight = QMAX(heightForEach, preferredHeight);

			window->setGeometry( 0, y, pMdiArea->width(), actHeight );
			y += actHeight;
		}
	}
}

/** minimize all windows */
void DCGuiApp::slotWindowMinimize()
{
	int i;
	
	QList<QMdiSubWindow*> windows = pMdiArea->subWindowList();
	
	for ( i = 0; i < windows.count(); i++ )
	{
		if ( windows.at(i)->isVisible() )
			windows.at(i)->showMinimized();
	}
}

/** close all chat windows */
void DCGuiApp::slotWindowCloseAllChats()
{
	g_pConnectionManager->CloseAllChats(false);
}

/** */
void DCGuiApp::slotWindowCloseOfflineChats()
{
	g_pConnectionManager->CloseAllChats(true);
}

/** close all chat windows */
void DCGuiApp::slotWindowCloseHubs()
{
	g_pConnectionManager->CloseDisconnectedHubs();
}

/** */
void DCGuiApp::slotWindowCloseFilelists()
{
	closeWindowsOfClass("DCFileBrowser");
}

/** */
void DCGuiApp::slotWindowCloseSearches()
{
	closeWindowsOfClass("DCHubSearch");
}

/** */
void DCGuiApp::slotFileOptions()
{
	DCOptions * od;

	statusBar()->showMessage(tr("Open options dialog..."));

	od = new DCOptions(this);

	od->SetValues();

	if ( QDialog::Accepted == od->exec() )
	{
		// move values to dcconfig
		od->GetValues();
		// save values
		g_pConfig->Save();
		// update connected servers
                g_pConnectionManager->SendMyInfoToConnectedServers();
	}

	/*
	 * set theme only if it has changed, or reset theme if a different one was tested
	 * also set theme if one theme was tested, but the old theme then saved
	 * but no need to set the theme if it was set with the test button
	 * od->GetTestedTheme() == old value of g_pConfig->GetTheme() if test button not pressed
	 */
	if ( od->GetTestedTheme() != g_pConfig->GetTheme() )
	{
		SetTheme();
	}

	delete od;

	statusBar()->showMessage(tr("Ready."));
}

/** */
void DCGuiApp::slotFileFileListBrowser()
{
	g_pTransferView->NewFileBrowser(QString::null,QString::null,QString::null,QString::null);
}

/** */
void DCGuiApp::slotFileFileListBrowserLocal()
{
	g_pTransferView->NewLocalFileBrowser(false);
}

/** */
void DCGuiApp::slotFileReloadPlugins()
{
	g_pPluginManager->DeInitPlugins();
	g_pPluginManager->Load();
}

/** */
void DCGuiApp::slotFileQuickOptions()
{
	pQuickOptionsMenu->exec(QCursor::pos());
}

/** */
void DCGuiApp::slotChangeDefaultDldMode(QAction* DldType)
{
	DldType->setChecked(true);
	if (fileDefaultDldAsk->isChecked())
	{
		g_pConfig->SetDefaultDownloadMode(eDownloadAsk);
	}
	else if (fileDefaultDldSingle->isChecked())
	{
		g_pConfig->SetDefaultDownloadMode(eDownloadSingle);
	}
	else  if (fileDefaultDldMulti->isChecked())
	{
		g_pConfig->SetDefaultDownloadMode(eDownloadMulti);
	}
}

/** */
void DCGuiApp::slotFileCreateShare()
{
	QString s;

	if ( CFileManager::Instance()->CreateShareList() )
		s = tr("Refresh share in progress.");
	else
		s = tr("Refresh share already in progress.");

	statusBar()->showMessage(s);
}

/** */
bool DCGuiApp::slotFileQuit()
{
	StringMap * map;
	StringMap * tabBarMap;

	statusBar()->showMessage(tr("Exiting application..."));

	if ( g_pConfig->GetQueryOnExit() )
	{
		if ( queryExit() == false )
		{
			statusBar()->showMessage(tr("Exiting application... aborted"));
			return false;
		}
	}

	// close all search windows
	slotWindowCloseSearches();

	// shutdown all transfers
	g_pTransferView->DLM_Shutdown();
	// stop running searches
	CSearchManager::Instance()->StopSearch();
	// close all clients
	g_pConnectionManager->DisconnectAllClients();

	while( (g_pTransferView->DLM_ShutdownState() != essSHUTDOWNREADY) ||
	       (CSearchManager::Instance()->IsSearch()) ||
	       (g_pConnectionManager->GetConnectedHubCount() > 0) )
	{
		qApp->processEvents();
#ifdef WIN32
		Sleep(100);
#else
		usleep(100);
#endif
	}

	// close all hub windows
	g_pConnectionManager->CloseDisconnectedHubs();

	g_pConfig->SetTabBar(viewTabBar->isChecked());
	g_pConfig->SetToolBar(viewToolBar->isChecked());
	g_pConfig->SetStatusBar(viewStatusBar->isChecked());
	g_pConfig->SetAppGeometry( width(), height() );

	// save transfer view settings
	g_pConfig->GetMap("TRANSFERVIEW",map);

	(*map)["X"]      = QString().setNum(pTransferViewDock->x());
	(*map)["Y"]      = QString().setNum(pTransferViewDock->y());
	(*map)["WIDTH"]  = QString().setNum(pTransferViewDock->width());
	(*map)["HEIGHT"] = QString().setNum(pTransferViewDock->height());
	(*map)["DOCKED"] = QString().setNum(!(pTransferViewDock->isFloating()));
	
	/* Qt::Dock dock3;
	int index3;
	bool nl3;
	int extraOffset3;
	if ( getLocation( pTransferViewDock, dock3, index3, nl3, extraOffset3 ) )
	{
		(*map)["DOCK"] = QString().setNum(dock3);
		
		QString nlstring;
		if ( nl3 )
		{
			nlstring = "TRUE";
		}
		else
		{
			nlstring = "FALSE";
		}
		
		(*map)["NL"] = nlstring;
		(*map)["INDEX"] = QString().setNum(index3);
		(*map)["EXTRAOFFSET"] = QString().setNum(extraOffset3);
	} */

	// save tabbar position and state
	g_pConfig->GetMap("TABBAR", tabBarMap);
	(*tabBarMap)["X"]	= QString().setNum(windowsTabBar->x());
	(*tabBarMap)["Y"]	= QString().setNum(windowsTabBar->y());
	(*tabBarMap)["WIDTH"]	= QString().setNum(windowsTabBar->width());
	(*tabBarMap)["HEIGHT"]	= QString().setNum(windowsTabBar->height());
	(*tabBarMap)["DOCKED"]	= QString().setNum(!(windowsTabBar->isFloating()));

	g_pConfig->SetQMainWindowState(saveState());

        switch (g_pConfig->GetTransferViewType()){
            case etvtDOCK:
                g_pConfig->SetShowTransferWin( pTransferViewDock->isVisible() );

                break;
            case etvtWINDOW:
                if (g_pTransferView->GetContainer())
                    g_pConfig->SetShowTransferWin( g_pTransferView->GetContainer()->isVisible() );

                break;
        }

	// save transfer list settings
	g_pTransferView->DeInitDocument();

	// save hub list settings
	g_pHubListManager->DeInitDocument();

	// save spy view settings
	g_pSpy->DeInitDocument();

	// save user view settings
	g_pUsersList->DeInitDocument();

	// init main window
	g_pConfig->GetMap("MAINVIEW",map);
	(*map)["MAXIMIZED"] = QString().setNum(isMaximized());
	(*map)["DOCKED"]    = QString().setNum(!(fileToolbar->isFloating()));
        //(*map)["USETABS"]   = QString().setNum(viewUseTabs->isChecked());

	if ( pMdiArea->property("tabPosition").isValid() )
	{
		map->insert( "TABPOSITION", pMdiArea->property("tabPosition").toString() );
	}

	/* Qt::Dock dock;
	int index;
	bool nl;
	int  extraOffset;

	if ( getLocation( fileToolbar, dock, index, nl, extraOffset ) )
	{
		(*map)["DOCK"] = QString().setNum(dock);
	} */
	
	/* Qt::Dock dock2;
	int index2;
	bool nl2;
	int extraOffset2;
	
	if ( getLocation( windowsTabBar, dock2, index2, nl2, extraOffset2 ) )
	{
		(*tabBarMap)["DOCK"] = QString().setNum(dock2);
		
		QString nlstring;
		if ( nl2 )
		{
			nlstring = "TRUE";
		}
		else
		{
			nlstring = "FALSE";
		}
		
		(*tabBarMap)["NL"] = nlstring;
		(*tabBarMap)["INDEX"] = QString().setNum(index2);
		(*tabBarMap)["EXTRAOFFSET"] = QString().setNum(extraOffset2);
	} */

	// save gui config
	g_pConfig->SaveDCGui();

	m_pTimer->stop();

        ready2Unload = true;

	qApp->quit();

	statusBar()->showMessage(tr("Ready."));

        return ready2Unload;

}

/** */
void DCGuiApp::slotViewTabBar(bool toggle)
{
	statusBar()->showMessage(tr("Toggle tabbar..."));
	///////////////////////////////////////////////////////////////////
	// turn Toolbar on or off
	if (toggle== false)
	{
		windowsTabBar->hide();
	}
	else
	{
		windowsTabBar->show();
	}

	statusBar()->showMessage(tr("Ready."));
}

/** */
void DCGuiApp::slotViewToolBar(bool toggle)
{
	statusBar()->showMessage(tr("Toggle toolbar..."));
	///////////////////////////////////////////////////////////////////
	// turn Toolbar on or off
	if (toggle== false)
	{
		fileToolbar->hide();
	}
	else
	{
		fileToolbar->show();
	}

	statusBar()->showMessage(tr("Ready."));
}

/** */
void DCGuiApp::slotViewStatusBar(bool toggle)
{
	statusBar()->showMessage(tr("Toggle statusbar..."));
	///////////////////////////////////////////////////////////////////
	//turn Statusbar on or off

	if (toggle == false)
	{
		statusBar()->hide();
	}
	else
	{
		statusBar()->show();
	}

	statusBar()->showMessage(tr("Ready."));
}

/** dock the application */
void DCGuiApp::slotViewDock()
{
	if ( !m_pTrayIcon )
	{
		QMessageBox::information(this, tr("Dock Application"), tr("The system tray icon must be enabled to dock the application."));
		return;
	}
	
	statusBar()->showMessage(tr("Dock/Undock application..."));
	///////////////////////////////////////////////////////////////////
	//dock/undock the application
	if ( m_bTray )
	{
		if ( m_bWasMaximized )
		{
			showMaximized();
		}
		else
		{
			show();
		}
		// show dcgui in front of any applications after undock
		raise();
		// restore desktop position
		move(m_DesktopPosition);

		m_bTray = false;
	}
        else if (!m_bTray && g_pConfig->GetInTray())
        {
                if ( m_bWasMaximized )
                {
                        showMaximized();
                }
                else
                {
                        show();
                }

                if ( pTransferViewDock->widget() == 0)
                {
                    if  (g_pConfig->GetTransferViewType() == etvtDOCK){
                        slotActionTransferList();
                        slotActionTransferList();
                    }
                }

        }
	else
	{
                if ( isMinimized() )
		{
			showNormal();
		}
		else
		{
			// save old desktop position
			m_DesktopPosition = pos();
			// save old maximized status
			m_bWasMaximized = isMaximized();
			
			if ( pTransferViewDock->isVisible() && pTransferViewDock->isFloating() )
			{
				m_bTransferViewGotTrayed = true;
				pTransferViewDock->hide();
			}
			else
			{
				m_bTransferViewGotTrayed = false;
			}
			
			// hide application
			hide();
                        //g_pConfig->SetInTray(true);
			m_bTray = true;
		}
	}

        g_pConfig->SetInTray(!this->isVisible());

	statusBar()->showMessage(tr("Ready."));
}

/** */
void DCGuiApp::slotHelpAbout()
{
	QString s;
	QDialog * dlg = 0;
	Ui::DCDialogAbout ui;
	ulonglong up = CSocket::m_Traffic.GetTraffic(ettTX);
	ulonglong down = CSocket::m_Traffic.GetTraffic(ettRX);
	double ratio = 0;
	
	if ( down > 0 )
	{
		ratio = (double) up / (double) down;
	}
	
	dlg = new QDialog(this);
	ui.setupUi(dlg);
	
	s  = ui.TextLabel2->text();
	
	s += "\n\n";
	s += tr("EiskaltDC ");
	s += PACKAGE_VERSION;
	s += " (";
	s += EISKALTDC_BUILD_INFO;
	s += ")\n";
	s += tr("Using dclib ");
	s += dclibVersion();
	s += " (";
	s += dclibBuildInfo();
	s += ")\n";
	s += trUtf8("Using Qt® ");
	s += qVersion();
	
	s += "\n\n";
	s += tr("Ratio: Overall: ");
	s += QString().setNum( ratio, 'f', 2 );
	s += tr(" (Up: ");
	s += DCGuiUtils::GetSizeString( up );
	s += tr(", Down: ");
	s += DCGuiUtils::GetSizeString( down );
	s += tr(")\nThis session: ");
	
	up -= g_pConfig->GetStartUploaded();
	down -= g_pConfig->GetStartDownloaded();
	
	if ( down > 0 )
	{
		ratio = (double) up / (double) down;
	}
	else
	{
		ratio = 0;
	}
	
	s += QString().setNum( ratio, 'f', 2 );
	s += tr(" (Up: ");
	s += DCGuiUtils::GetSizeString( up );
	s += tr(", Down: ");
	s += DCGuiUtils::GetSizeString( down );
	s += ")";

	ui.TextLabel_VERSION->setText( QString("EiskaltDC ") + QString(PACKAGE_VERSION) );
	dlg->setWindowIcon( QIcon( g_pIconLoader->GetPixmap(eiINFO) ) );
	ui.PixmapLabel_ICON->setPixmap( g_pIconLoader->GetPixmap(eiICON_22x22) );

	ui.TextLabel2->setText( s );

/* not usually done but is allowed, including a file in the middle of a function */
#include "about.h"
	ui.TextEdit_AUTHORS->setHtml(g_sAboutAuthors);

	// load license file
	QFile f(g_pConfig->GetValknutDataPath() + DIRSEPARATOR + "COPYING");
	
	if ( f.open(QIODevice::ReadOnly) )
	{
		QTextStream t( &f );
		t.setCodec("UTF-8");
		ui.TextEdit_LICENSE->setPlainText( t.readAll() );
	}
	else
	{
		ui.TextEdit_LICENSE->append(tr("Warning license file not found !"));
	}
	
	dlg->exec();

	delete dlg;
}

/** open the online manual in web browser */
void DCGuiApp::slotHelpManual()
{
	g_pConfig->OpenURL( "http://wxdcgui.sourceforge.net/doc/manual.html" );
}

/** connect to the valknut hub */
void DCGuiApp::slotHelpSupport()
{
	// TODO: Check to see if we are already connected or not.
	g_pConnectionManager->Connect(CString(),"valknut.dyndns.info:59176");
}

/** change user away mode */
void DCGuiApp::slotChangeAwayMode()
{
	switch(g_pConfig->GetAwayMode())
	{
		case euamAWAY:
			actionAwayModeNormal->setChecked(true);
			g_pConfig->CConfig::SetAwayMode(euamNORMAL);
			break;
		default:
			actionAwayModeAway->setChecked(true);
			g_pConfig->CConfig::SetAwayMode(euamAWAY);
			break;
	}

	g_pConnectionManager->SendMyInfoToConnectedServers();
}

/** */
void DCGuiApp::slotAwayModeChanged( eUserAwayMode mode )
{
	if ( mode == euamNORMAL )
	{
		actionAwayModeNormal->setChecked(true);
	}
	else
	{
		actionAwayModeAway->setChecked(true);
	}
}

/** */
void DCGuiApp::windowMenuAboutToShow()
{
	int i = 0;

	pWindowMenu->clear();
	pWindowMenu->addAction(windowCascade);
	pWindowMenu->addAction(windowTile);
	pWindowMenu->addAction(windowTileHor);
	pWindowMenu->addAction(windowMinimize);
	pWindowMenu->addSeparator();
	pWindowMenu->addAction(windowCloseHubs);
	pWindowMenu->addAction(windowCloseAllChats);
	pWindowMenu->addAction(windowCloseOfflineChats);
	pWindowMenu->addAction(windowCloseFilelists);
	pWindowMenu->addAction(windowCloseSearches);

	QList<QMdiSubWindow*> windows = pMdiArea->subWindowList();
	qDeleteAll( windowsGroup->actions() );

	//printf("window list length =%d\n", windows.size());
	
	for ( i = 0; i < windows.count(); i++ )
	{
		QAction * act = windowsGroup->addAction(QString("&%1 ").arg(i+1)+windows.at(i)->windowTitle());
		act->setData( i );
		act->setCheckable( true );
		act->setChecked( pMdiArea->activeSubWindow() == windows.at(i) );
		
		if ( i == 0 )
		{
			pWindowMenu->addSeparator();
		}
		
		pWindowMenu->addAction( act );
	}

	if ( i == 0 )
	{
		windowAction->setEnabled(false);
	}
	else
	{
		windowAction->setEnabled(true);
	}
}

/** */
void DCGuiApp::windowMenuActivated( QAction * action )
{
	if ( action )
	{
		QMdiSubWindow * w = pMdiArea->subWindowList().at( action->data().toInt() );
		if ( w )
		{
			w->show();
			w->setFocus();
		}
	}
}

/** show/hide transfer list window */
void DCGuiApp::slotActionTransferList()
{
	statusBar()->showMessage(tr("Show/hide transfer list window ..."));

        if (g_pConfig->GetTransferViewType() == etvtNONE)
            slotActionTransferViewType();

        eTransferViewType t_type = g_pConfig->GetTransferViewType();

	if ( g_pTransferView != 0 )
	{
            if (g_pTransferView->isVisible()){
                if (t_type == etvtDOCK){
                        pTransferViewDock->hide();
                }
                else{
                    if (g_pTransferView->GetContainer()) {
                        g_pTransferView->GetContainer()->close();
                        g_pTransferView->deinitContainer();
                    }
                }
            }
            else{
                if (t_type == etvtDOCK){
                        pTransferViewDock->setWidget(g_pTransferView);
                        pTransferViewDock->show();
                }
                else{
                        g_pTransferView->initContainer();

                        showMDIWidget(g_pTransferView->GetContainer());
                        g_pTransferView->GetContainer()->setWindowIcon( QIcon(g_pIconLoader->GetPixmap(eiTRANSFER)) );

                        connect(g_pTransferView, SIGNAL(onDie(QWidget*)), this, SLOT(slotChildOnDie(QWidget*)));

                        g_pConnectionManager->addTab(g_pTransferView, QApplication::translate("DCDialogTransfer", "Transfer List", 0, QApplication::UnicodeUTF8));
                }
            }
	}

        showNotification(QApplication::translate("DCDialogTransfer", "Transfer List", 0, QApplication::UnicodeUTF8), "Hi!");

	statusBar()->showMessage(tr("Ready."));
}

/** show/hide mdi widget */
void DCGuiApp::showMDIWidget( QMdiSubWindow * window )
{
	if ( window != 0 )
	{
		if ( window->parent() == 0 )
		{
			/* well this is as stupid as it looks */
			const QPoint oldpos = window->pos();
			pMdiArea->addSubWindow( window );
			window->move(oldpos);
		}
		
		if ( window->isMinimized() )
		{
			window->showNormal();
			window->widget()->showNormal();
		}
		else if ( window->isVisible() )
		{
			if ( pMdiArea->activeSubWindow() == window )
			{
				window->close();
			}
			else
			{
				pMdiArea->setActiveSubWindow(window);
			}
		}
		else if ( window->isMaximized() )
		{
			window->showMaximized();
			window->widget()->showMaximized();
		}
		else
		{
			window->show();
			window->widget()->show();
		}
	}
}

/** show/hide server list window */
void DCGuiApp::slotActionServerList()
{
	statusBar()->showMessage( tr("Show/hide hub list window ...") );

        QMdiSubWindow *wnd = g_pHubListManager->GetMdiSubWindow();

        if (wnd->isVisible()){
            wnd->close();
            return;
        }

        showMDIWidget(wnd);

        DCHubListManager *mngr = g_pHubListManager;
        connect(mngr, SIGNAL(onDie(QWidget*)), this, SLOT(slotChildOnDie(QWidget*)));
        mngr->setWindowIcon( QIcon(g_pIconLoader->GetPixmap(eiSERVER)) );

        g_pConnectionManager->addTab((QWidget*)mngr,
                                     QApplication::translate("DCDialogHubListManager", "Hub List", 0, QApplication::UnicodeUTF8));

	statusBar()->showMessage(tr("Ready."));
}

/** show/hide multi hub search window */
void DCGuiApp::slotActionHubSearch()
{
	statusBar()->showMessage(tr("Open hub search window ..."));

	DCHubSearch * hubsearch = new DCHubSearch( pMdiArea );
        connect(hubsearch, SIGNAL(onDie(QWidget*)), this, SLOT(slotChildOnDie(QWidget*)));
        hubsearch->setWindowIcon(QIcon(g_pIconLoader->GetPixmap(eiFIND)));
        hubsearch->show();

        g_pConnectionManager->addTab((QWidget*)hubsearch,
                                     QApplication::translate("DCDialogHubSearch", "Hub Search", 0, QApplication::UnicodeUTF8));

	statusBar()->showMessage(tr("Ready."));
}

/** show/hide spy window */
void DCGuiApp::slotActionSpy()
{
	statusBar()->showMessage(tr("Show/hide spy window ..."));

        QMdiSubWindow *wnd = g_pSpy->GetMdiSubWindow();

        if (wnd->isVisible()){
            wnd->close();
            return;
        }

        showMDIWidget(wnd);

        DCSpy *spy = g_pSpy;
        spy->setWindowIcon( QIcon(g_pIconLoader->GetPixmap(eiSPY)) );
        connect(spy, SIGNAL(onDie(QWidget*)), this, SLOT(slotChildOnDie(QWidget*)));

        g_pConnectionManager->addTab((QWidget*)spy, QApplication::translate("DCDialogSpy", "Spy", 0, QApplication::UnicodeUTF8));

	statusBar()->showMessage(tr("Ready."));
}

/** show/hide users window */
void DCGuiApp::slotActionUsers()
{
	statusBar()->showMessage(tr("Show/hide users window ..."));

        QMdiSubWindow *wnd = g_pUsersList->GetMdiSubWindow();

        if (wnd->isVisible()){
            wnd->close();
            return;
        }

        showMDIWidget(wnd);

        DCUsersList *user_lst = g_pUsersList;
        connect(user_lst, SIGNAL(onDie(QWidget*)), this, SLOT(slotChildOnDie(QWidget*)));
        g_pConnectionManager->addTab((QWidget*)user_lst, QApplication::translate("DCDialogUsersList", "Users List", 0, QApplication::UnicodeUTF8));

	statusBar()->showMessage(tr("Ready."));
}

void DCGuiApp::slotActionAntiSpam()
{
    DCAntiSpamControl *wnd = new DCAntiSpamControl(this);
    wnd->setWindowModality(Qt::WindowModal);
    wnd->setAttribute(Qt::WA_DeleteOnClose);

    wnd->exec();
}


void DCGuiApp::slotActionIPFilter()
{
    DCIPFilterControl *wnd = new DCIPFilterControl(this);
    wnd->setWindowModality(Qt::WindowModal);
    wnd->setAttribute(Qt::WA_DeleteOnClose);

    wnd->exec();
}

/** Called when the tray icon is activated */
void DCGuiApp::slotTrayMenuTriggered( QSystemTrayIcon::ActivationReason reason )
{
	// if single clicked
	if ( reason == QSystemTrayIcon::Trigger )
	{
		slotViewDock();
	}
}

/** Called when the remove item is chosen from the tray icon's menu */
void DCGuiApp::slotRemoveTrayIcon()
{
	// undock if docked!
	if ( m_bTray )
	{
		slotViewDock();
	}
	
	deinitTray();
	
	viewTrayIcon->setChecked(false);
	viewDock->setEnabled(false);	
	g_pConfig->SetEnableTray(false);
}

/** */
void DCGuiApp::SetTheme()
{
	if ( g_pConfig->GetThemeSupport() )
	{
		QString s = g_pConfig->GetTheme();

		if ( s.isEmpty() )
		{
			printf("Can't set empty theme\n");
		}
		else
		{
			QApplication::setStyle( s );
		}
	}
}

/** */
void DCGuiApp::slotDefaultDownloadModeChanged()
{
	switch (g_pConfig->GetDefaultDownloadMode())
	{
		case eDownloadAsk: fileDefaultDldAsk->setChecked(true); break;
		case eDownloadSingle: fileDefaultDldSingle->setChecked(true); break;
		case eDownloadMulti: fileDefaultDldMulti->setChecked(true); break;
		default: break;
	}
}

/** */
void DCGuiApp::slotViewTrayIcon( bool toggle )
{
	g_pConfig->SetEnableTray( toggle );
	
	if ( toggle )
	{
		initTray();
	}
	else
	{
		deinitTray();
	}
	
	viewDock->setEnabled( toggle );
}

/** */
void DCGuiApp::closeWindowsOfClass( QString classname )
{
	QList<QMdiSubWindow*> windows = pMdiArea->subWindowList( QMdiArea::CreationOrder );
	
	for ( int i = 0; i < windows.size(); ++i )
	{
		if ( windows.at(i)->widget() && (windows.at(i)->widget()->metaObject()->className() == classname) )
		{
			windows.at(i)->close();
		}
	}
}

/** */
void DCGuiApp::slotContextMenuTraffic( const QPoint & /* pos */ )
{
	QMenu * m =  new QMenu(this);
	
	QAction * reset = DCMenuHandler::addAction( m, emiRESET );
	
	QAction * chosen = m->exec(QCursor::pos());
	
	delete m;
	
	if ( chosen == reset )
	{
		CSocket::m_Traffic.ResetTraffic();
		g_pConfig->ResetSessionStats();
		statusTRLabel->clear();
	}
}

/** */
void DCGuiApp::slotDebugSettings()
{
	QDialog * dialog = new QDialog(this);
	Ui::DCDialogDebugSettings ui;
	ui.setupUi(dialog);
	
	ui.ComboBox_PRINTF->setCurrentIndex(dclibVerbose());
	ui.ComboBox_SOCKETLOG->setCurrentIndex(CSocket::m_eSocketLog);
	
#if defined(HAVE_MALLINFO) || defined(HAVE_MALLOC_STATS)
	connect( ui.PushButton_MALLOC_INFO, SIGNAL(clicked()), this, SLOT(slotMallocInfo()) );
#else
	ui.PushButton_MALLOC_INFO->setEnabled(false);
#endif
	
	if ( dialog->exec() == QDialog::Accepted )
	{
		setdclibVerbose( ui.ComboBox_PRINTF->currentIndex() );
		switch ( ui.ComboBox_SOCKETLOG->currentIndex() )
		{
			case 0:
				CSocket::m_eSocketLog = eslNONE;
				break;
			case 1:
				CSocket::m_eSocketLog = eslSEND;
				break;
			case 2:
				CSocket::m_eSocketLog = eslRECV;
				break;
			case 3:
				CSocket::m_eSocketLog = eslBOTH;
				break;
			default:
				CSocket::m_eSocketLog = eslNONE;
				break;
		}
	}
	
	delete dialog;
}

/** */
void DCGuiApp::slotMallocInfo()
{
#if defined(HAVE_MALLOC_STATS)
	fprintf(stderr, "%s %s malloc_stats()\n", PACKAGE_STRING, QDateTime::currentDateTime().toString().toLocal8Bit().constData());
	malloc_stats();
#endif

#if defined(HAVE_MALLINFO)
	struct mallinfo mi = mallinfo();
	
	/* this stuff is for debugging so is not translated or even explained */
	QMessageBox * mb = new QMessageBox( pMdiArea );
	mb->setAttribute( Qt::WA_DeleteOnClose );
	mb->setIcon( QMessageBox::Information );
	mb->setWindowTitle( "mallinfo" );
	mb->setText(
		QDateTime::currentDateTime().toString() +
		"\n\narena " + QString::number(mi.arena) +
		"\nordblks " + QString::number(mi.ordblks) +
		"\nsmblks " + QString::number(mi.smblks) +
		"\nhblks " + QString::number(mi.hblks) +
		"\nhblkhd " + QString::number(mi.hblkhd) +
		"\nusmblks " + QString::number(mi.usmblks) +
		"\nfsmblks " + QString::number(mi.fsmblks) +
		"\nuordblks " + QString::number(mi.uordblks) +
		"\nfordblks " + QString::number(mi.fordblks) +
		"\nkeepcost " + QString::number(mi.keepcost)
	);
	mb->setModal( false );
	mb->show();
#endif
}

/** */
void DCGuiApp::slotAutoAwayModeChanged( bool enabled )
{
	if ( enabled )
	{
		qApp->installEventFilter( &m_ApplicationEvents );
	}
	else
	{
		qApp->removeEventFilter( &m_ApplicationEvents );
	}
	
	m_ApplicationEvents.m_nNoUserInputTimer = 0;
}

void DCGuiApp::slotChildOnDie(QWidget *wnd){
    if (!wnd)
        return;
    g_pConnectionManager->remTab(wnd);
}

void DCGuiApp::slotActionTransferViewType()
{

    eTransferViewType t_type = g_pConfig->GetTransferViewType();
    QMessageBox msg_box;
    QPushButton *dock_btn, *wind_btn;

    dock_btn = msg_box.addButton( tr("Dock mode"), QMessageBox::YesRole);
    wind_btn = msg_box.addButton( tr("Window mode"), QMessageBox::YesRole );

    msg_box.setText( tr("Please, select transfer view type") );

    msg_box.exec();

    if (msg_box.clickedButton() == dock_btn)
        g_pConfig->SetTransferViewType(etvtDOCK);
    else if (msg_box.clickedButton() == wind_btn)
        g_pConfig->SetTransferViewType(etvtWINDOW);
    else
        return;

    if (t_type != etvtNONE){
        if (t_type == etvtDOCK && ( msg_box.clickedButton() == wind_btn)){
            pTransferViewDock->hide();
            pTransferViewDock->setWidget(0);
            removeDockWidget(pTransferViewDock);

            g_pTransferView->initContainer();

            showMDIWidget(g_pTransferView->GetContainer());
            connect(g_pTransferView, SIGNAL(onDie(QWidget*)), this, SLOT(slotChildOnDie(QWidget*)));

            g_pConnectionManager->addTab(g_pTransferView, QApplication::translate("DCDialogTransfer", "Transfer List", 0, QApplication::UnicodeUTF8));
        }
        else{
            if (g_pTransferView->GetContainer()){
                g_pTransferView->GetContainer()->close();
                g_pTransferView->deinitContainer();
            }
            pTransferViewDock->setWidget(g_pTransferView);
            addDockWidget(Qt::BottomDockWidgetArea, pTransferViewDock);
            pTransferViewDock->show();
        }
    }
    else{
        switch (t_type){
            case etvtDOCK:
                pTransferViewDock->setWidget(g_pTransferView);
                pTransferViewDock->show();

                break;
            case etvtWINDOW:
            default:
                pTransferViewDock->hide();
                pTransferViewDock->setWidget(0);

                g_pTransferView->initContainer();

                showMDIWidget(g_pTransferView->GetContainer());
                connect(g_pTransferView, SIGNAL(onDie(QWidget*)), this, SLOT(slotChildOnDie(QWidget*)));

                g_pConnectionManager->addTab(g_pTransferView, QApplication::translate("DCDialogTransfer", "Transfer List", 0, QApplication::UnicodeUTF8));

                break;
        }
    }

}

void DCGuiApp::WakeUp()
{
    if (m_bTray){
        slotViewDock();
        return;
    }
    if (!this->isVisible()){
        show();
        raise();
    }
}

void DCGuiApp::showNotification(QString sender, QString message, eTrayMessageType type)
{
    if (!g_pConfig->GetEnableTray() || isActiveWindow() || isVisible())
        return;

    TrayMessageType t_type = g_pConfig->GetTrayMessageType();

    if (IS_TRAY_MSG_NONE(t_type))
        return;

    if ((!IS_TRAY_MSG_DISC(t_type) && (type == eTrayMessageTypeDISC)) ||
        (!IS_TRAY_MSG_NICK(t_type) && (type == eTrayMessageTypeNICK)) ||
        (!IS_TRAY_MSG_PRIV(t_type) && (type == eTrayMessageTypePRIV))  )
    {
        return;
    }

    QString popup = QDir::homePath() + "/.eiskaltdc/popup.sh";

    if (QFile::exists(popup)){
        QProcess proc(this);
        QStringList args;

        args << popup << "\"" + sender + "\"" << "\"" +message + "\"";

        proc.start(QString("sh"), args);

        proc.waitForFinished(200);

        return;
    }


    if ((IS_TRAY_MSG_DISC(t_type) && (type == eTrayMessageTypeDISC)) ||
        (IS_TRAY_MSG_NICK(t_type) && (type == eTrayMessageTypeNICK)) ||
        (IS_TRAY_MSG_PRIV(t_type) && (type == eTrayMessageTypePRIV))  )
    {
        m_pTrayIcon->showMessage(sender + ":\n\t", message);
    }
}

void DCGuiApp::slotFileQuickConnect()
{
    DCQuickConnect *qc = new DCQuickConnect( this );
    qc->setAttribute( Qt::WA_DeleteOnClose );
    qc->setWindowModality( Qt::WindowModal );

    qc->exec();
}


#ifndef WIN32

void DCGuiApp::slotInotify()
{
    if (g_pInotifyControl){
        g_pInotifyControl->setWindowModality(Qt::WindowModal);

        g_pInotifyControl->exec();

        g_pInotifyControl->setWindowModality(Qt::NonModal);
    }
}

void DCGuiApp::slotFileInotifyEnable()
{
    g_pConfig->SetInotifyEnabled(fileInotifyEnable->isChecked());

    if (g_pConfig->GetInotifyEnabled()){
        new DCInotifyControl (this);

        fileInotify->setEnabled(true);
    }
    else{
        if (g_pInotifyControl)
            g_pInotifyControl->Shutdown();

        fileInotify->setEnabled(false);
    }
}
#endif

void DCGuiApp::slotClearCurrentChat()
{
    if (g_pActiveChat)
        g_pActiveChat->ClearChat();
}

void DCGuiApp::slotChatZoomIn()
{
    if (g_pActiveChat)
        g_pActiveChat->ZoomIn();
}

void DCGuiApp::slotChatZoomOut()
{
    if (g_pActiveChat)
        g_pActiveChat->ZoomOut();
}

void DCGuiApp::slotChatOff()
{
    if (g_pActiveChat)
        g_pActiveChat->SetChatOff();
}

void DCGuiApp::SetChatOff(bool b)
{
    chatOff->setChecked(b);

    if (b){
        chatOff->setText(tr("Enable chat"));
        chatOff->setStatusTip(tr("Enable chat output"));
    }
    else{
        chatOff->setText(tr("Disable chat"));
        chatOff->setStatusTip(tr("Disable chat output"));
    }
}

void DCTabBar::mousePressEvent(QMouseEvent *e)
{
    e->accept();

    QTabBar::mousePressEvent(e);

    if (e->button() == Qt::MidButton){

        QPoint p = mapFromGlobal(QCursor::pos());
        int tab = this->tabAt(p);

        QWidget *wgt = g_pConnectionManager->GetWidgetForTab(tab);

        if (wgt)
            wgt->close();
    }
}

void DCTabBar::wheelEvent(QWheelEvent *we)
{
    int new_index = 0;

    if (we->delta() < 0 && currentIndex() > 0)
        new_index = currentIndex()-1;
    else if (we->delta() > 0 && currentIndex() < (count()-1))
        new_index = currentIndex()+1;
    else
        new_index = currentIndex();

    setCurrentIndex(new_index);

    emit currentChanged(new_index);

    we->accept();
}
