/***************************************************************************
 *   Copyright (C) 2004 by yunfan                                          *
 *   yunfan_zg@163.com                                                     *
 *                                                                         *
 *   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.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/


#include "evamain.h"

#include "evautil.h"

#include "evaapi.h"

#include "evaui.h"

#include "evachatwindowmanager.h"
#include "evasystemtray.h"

#include <unistd.h>
#include <qimage.h>
#include <qtimer.h>
#include <qtextcodec.h>
#include <qdatetime.h>
#include <qhostaddress.h>
#include <qpopupmenu.h>
#include <kapplication.h>
#include <kaboutdata.h>
#include <kaboutapplication.h>
#include <kglobalaccel.h>
#include <kwin.h>
#include <kmessagebox.h>

#define MaxRetryTimes  5

KAboutData * EvaMain::mAboutData = NULL;
EvaUser *EvaMain::user = NULL;
EvaImageResource *EvaMain::images = NULL;
EvaHelper *EvaMain::helper = NULL;
EvaConnecter *EvaMain::connecter = NULL;
EvaPicManager *EvaMain::picManager = NULL;
EvaUHManager *EvaMain::uhManager = NULL;

EvaMain::EvaMain() :
	packetManager(NULL),
	numOfLostKeepAlivePackets(0),
	aboutEva(NULL),
	sysMenu(NULL),
	statusMenu(NULL),
	autoMenu(NULL),
	windowList(NULL),
	accelKey(NULL)
{
	loggedIn=false;
	isClientSet=false;
	numLoginRetry = 0;
	deleteFromQQ = -1;
	EvaUtil::initMap();
	codec = QTextCodec::codecForName("GB18030");
	onlineFriendTimer = new QTimer();
	loginWin = new EvaLoginWindow(0);
	mainWin = new EvaMainWindow(0);
	tray = new EvaSystemTray(mainWin);
	helper = new EvaHelper();
	initSettings();
	if(!doInitUI()){
		doQuit();
	}
	doSlotConnection();
	loginWin->show();
}

EvaMain::~EvaMain()
{
	delete loginWin;
	delete mainWin;
	delete packetManager;
	
	if(aboutEva) delete aboutEva;
	if(helper->running())
		helper->terminate();
	delete helper;
	if(uhManager){
		uhManager->stop();
		uhManager->wait();
		delete uhManager;
	}
}

void EvaMain::initSettings()
{
	global = new EvaGlobal();
	if(!global->loadImage()) {
		KMessageBox::information(0, i18n("Sorry, image resource cannot be loaded properly, check image directory please."),
					i18n("Eva Initializing"));
		exit(0);
	}
	global->setFaceSize(QSize(16, 16));
	images = global->getImageResource();
	sysSetting = global->getEvaSetting();
	QObject::connect(images, SIGNAL(qqShowReady(const int)), this, SLOT(slotQQShowReady(const int)));
	
	_wallet = 0;
}

void EvaMain::slotLoadGroupedBuddiesReady()
{
	if(loggedIn) return;
	QString nick = codec->toUnicode(user->getDetails().at(ContactInfo::Info_nick).c_str()); // once load, nick name should be right
	int faceId = atoi(user->getDetails().at(ContactInfo::Info_face).c_str());
	QPixmap *face = images->getFace(images->getFaceFileIndex(faceId));
	if(user->hasUserHead()){
		QPixmap *uhPic = images->getUserHeadPixmap(user->getQQ());
		if(uhPic) face = uhPic;
	}
	mainWin->setCaption(nick + " - Eva");
	mainWin->setIcon(*face);
	mainWin->setMainInfo(user->getQQ(), nick, face?face:images->getFace(0)); 
	windowList->setMyName(nick, user->getQQ());
	initGroups();
	slotFriendListReady();
	tray->changeToolTip(user->getQQ(), nick, faceId);
}

void EvaMain::slotLoadQunListReady()
{
	mainWin->clearQunList();
	QunList *qunList = user->getQunList();
	if(qunList && qunList->numQuns()){
		std::list<Qun>::iterator iter;
		std::list<Qun> list = qunList->getQunList();
		for(iter=list.begin(); iter!=list.end(); ++iter){
			QunInfo info = iter->getDetails();
			QString name = "";
			if(!info.getQunID())
				name = QString::number(iter->getQunID());
			else
				name = EvaTextFilter::filter(codec->toUnicode(info.getName().c_str()));
			mainWin->addQun(name, iter->getQunID(), images->getIcon("QUN"));
		}
		
	}
}

void EvaMain::doAbout()
{
	if(mAboutData){
		if(!aboutEva){
			aboutEva = new KAboutApplication(mAboutData, mainWin, "About", false);
		}
		aboutEva->setLogo(*(images->getIcon("EVA")));
		aboutEva->show();
	}
}

void EvaMain::doQuit()
{
	if(onlineFriendTimer->isActive())
		onlineFriendTimer->stop();
	if(loggedIn || packetManager)
		packetManager->doLogout();
	if(uhManager){
		uhManager->stop();
		uhManager->wait();
		delete uhManager;
	}
	
	KApplication::kApplication()->quit();
}

bool EvaMain::doInitUI()
{
	// login window	
	loginWin->setLogo(images->getIcon("EVALOGO"));
	loginWin->setIcon(*images->getIcon("EVA"));
	if(sysSetting){
		loginWin->setEvaSetting(sysSetting);
	}
	
	// main window
	mainWin->setBasicPixmaps(images->getIcon("SYSTEM_SETTING"), images->getIcon("OPEN"), images->getIcon("CLOSE"), 
				images->getIcon("NA"), images->getIcon("MSG"));
	mainWin->setStatusPixmaps(images->getIcon("ONLINE"), images->getIcon("OFFLINE"), 
				images->getIcon("LEAVE"), images->getIcon("INVISIBLE"));
	mainWin->setGroupMenu(images->getIcon("RENAME"), images->getIcon("ADD_GROUP"), images->getIcon("DEL_GROUP"), 
				images->getIcon("SHOW_ONLINE_BUDDIES"), images->getIcon("SHOW_ALL_BUDDIES"), images->getIcon("QUN"));
	mainWin->setBuddyMenu(images->getIcon("CHAT"), images->getIcon("TIME_SUN"), images->getIcon("DETAILS"), images->getIcon("HISTORY"), 
				images->getIcon("DEL_BUDDY"));
	mainWin->setQunMenu(images->getIcon("CHAT"), images->getIcon("DETAILS"), images->getIcon("HISTORY"), images->getIcon("QUN_EXIT"));
	mainWin->setOrgsMenu();
	mainWin->setDiscussMenu();
	initMenus();
	
	mainWin->setStatusMenu(statusMenu);
	mainWin->setSystemMenu(sysMenu);
	
	tray->setImagesResource(images);
	tray->setupMenus(sysMenu, statusMenu);
	
	EvaDetailsWindow::setImageResource(images);
	return true;
}

void EvaMain::initMenus()
{
	statusMenu = new QPopupMenu();
	statusMenu->insertItem(QIconSet(*(images->getIcon("ONLINE"))), i18n("Online"), this,SLOT(slotDoOnline()), -1);
	statusMenu->insertItem(QIconSet(*(images->getIcon("OFFLINE"))), i18n("Offline"), this,SLOT(slotDoOffline()), -1);
	statusMenu->insertItem(QIconSet(*(images->getIcon("LEAVE"))), i18n("Leave"), this,SLOT(slotDoLeave()), -1);
	statusMenu->insertItem(QIconSet(*(images->getIcon("INVISIBLE"))), i18n("Invisible"), this,SLOT(slotDoInvisible()), -1);
	
	sysMenu = new QPopupMenu();
	QPopupMenu *group = new QPopupMenu();
	
	
	sysMenu->insertItem(QIconSet(*(images->getIcon("QUIT"))), i18n("Quit"), this,SLOT(doQuit()), -1);
	sysMenu->insertSeparator(-1);

	group->insertItem(QIconSet(*(images->getIcon("UPLOAD_GROUPS"))), i18n("Upload Group"),this, SLOT(slotDoUploadGroups()), -1);
	group->insertItem(QIconSet(*(images->getIcon("DOWNLOAD_GROUPS"))), i18n("Download Group"),this, SLOT(slotDoDownloadGroups()), -1);
	
	sysMenu->insertItem(QIconSet(*(images->getIcon("GROUP"))), i18n("Group"),group);
	sysMenu->insertItem(QIconSet(*(images->getIcon("REFRESH_BUDDIES"))), i18n("Update Buddies"), this,SLOT(slotDoDownloadBuddies()), -1);
	sysMenu->insertSeparator(-1);
	sysMenu->insertItem(QIconSet(*(images->getIcon("SYSTEM_OPTIONS"))), i18n("System Options"),this, SLOT(slotRequestSystemSettingWindow()));
	sysMenu->insertItem(QIconSet(*(images->getIcon("CHANGE_USER"))), i18n("Change User"), this,SLOT(slotDoChangeUser()), -1);
	sysMenu->insertItem(QIconSet(*(images->getIcon("EVA"))), i18n("About Eva"), this,SLOT(doAbout()), -1);
}

void EvaMain::initUserLeaveMenu()
{
	if(!statusMenu) return;
	std::list<QString>::iterator iter;
	std::list<QString> autoList = user->getSetting()->getAutoReplyList();
	//if(!autoList.size()) return;
	
	statusMenu->removeItemAt(2);
	if(autoMenu) delete autoMenu;
	autoMenu = new QPopupMenu();
	autoMenu->setCheckable(true);
	autoMenu->insertItem(QString(i18n("No Auto-Reply")), 0);
	int id=1;
	for(iter=autoList.begin(); iter!=autoList.end(); ++iter){
		autoMenu->insertItem(*iter, id++);
	}
	autoMenu->setItemChecked(user->getSetting()->getAutoReplySelectedIndex()+1, true);
	statusMenu->insertItem(QIconSet(*(images->getIcon("LEAVE"))), i18n("Leave"), autoMenu, -1, 2);
	
	QObject::connect(autoMenu, SIGNAL(activated(int)), this,  SLOT(slotAutoReplyMenuActivated(int)));
}

void EvaMain::slotAutoReplyMenuActivated(int id)
{
	if(id==0)
		user->getSetting()->setAutoReplyEnabled(false);
	else
		user->getSetting()->setAutoReplyEnabled(true);
	user->getSetting()->setAutoReplySelectedIndex(id - 1);
	for(uint i=0; i <= user->getSetting()->getAutoReplyList().size(); i++){
		if((int)i==id)
			autoMenu->setItemChecked(i, true);
		else
			autoMenu->setItemChecked(i, false);
	}
	if(user->getStatus() != EvaUser::Eva_Leave)
		slotDoLeave();
}

void EvaMain::doSlotConnection()
{
	QObject::connect(onlineFriendTimer, SIGNAL(timeout()), this, SLOT(slotGetOnlineStatus()));
	QObject::connect(loginWin, SIGNAL(doLogin()), this, SLOT(slotDoLoginClick()));
	QObject::connect(loginWin, SIGNAL(doCancel()), this, SLOT(slotDoCancel()));
	
	QObject::connect(mainWin, SIGNAL(groupDeleted(const int)), this, SLOT(slotGroupDeleted(const int)));
	QObject::connect(mainWin, SIGNAL(groupAdded(QString, int)), this, SLOT(slotGroupAdded(QString, int)));
	QObject::connect(mainWin, SIGNAL(groupRenamed(QString, int)), this, SLOT(slotGroupRenamed(QString, int)));
	QObject::connect(mainWin, SIGNAL(deleteMeFrom(int)), this, SLOT(slotDeleteMeFrom(int)));
	QObject::connect(mainWin, SIGNAL(groupChanged(int, int)), this, SLOT(slotGroupChanged(int, int)));
	QObject::connect(mainWin, SIGNAL(requestAddBuddy(const int)), this, SLOT(slotRequestAddBuddy(const int)));
	QObject::connect(mainWin, SIGNAL(showOnlineSelected()), this, SLOT(slotShowOnlineSelected()));
	QObject::connect(mainWin, SIGNAL(showAllSelected()), this, SLOT(slotShowAllSelected()));
	
	
	QObject::connect(mainWin, SIGNAL(requestDelete(const int)), this, SLOT(slotRequestDelete(const int)));
	QObject::connect(mainWin, SIGNAL(requestDetails(const int)), this, SLOT(slotRequestDetails(const int)));
	QObject::connect(mainWin, SIGNAL(requestChat(const int)), this, SLOT(slotRequestChat(const int)));
	QObject::connect(mainWin, SIGNAL(requestLevel(const int)), this, SLOT(slotRequestLevel(const int)));
	QObject::connect(mainWin, SIGNAL(requestSearch()), this, SLOT(slotRequestSearch()));
	QObject::connect(mainWin, SIGNAL(requestSystemMessages()), this, SLOT(slotRequestSystemMessages()));
	QObject::connect(mainWin, SIGNAL(requestHistory(const int)), this, SLOT(slotRequestHistory(const int)));
	QObject::connect(mainWin, SIGNAL(requestQunChat(const int)), this, SLOT(slotRequestQunChat(const int)));
	QObject::connect(mainWin, SIGNAL(requestQunDetails(const int)), this, SLOT(slotRequestQunDetails(const int)));
	QObject::connect(mainWin, SIGNAL(requestQunExit(const int)), this, SLOT(slotDoQunExit( const int)));
	QObject::connect(mainWin, SIGNAL(requestQunCreate()), this, SLOT(slotQunCreate()));
	QObject::connect(mainWin, SIGNAL(requestQunHistory(const int)), this, SLOT(slotRequestQunHistory(const int)));
	
	QObject::connect(tray, SIGNAL(requestChat(const int)), this, SLOT(slotRequestChat(const int)));
	QObject::connect(tray, SIGNAL(requestQunChat(const int)), this, SLOT(slotRequestQunChat(const int)));
	QObject::connect(tray, SIGNAL(requestSystemMessage()), this, SLOT(slotRequestSystemMessage()));
}

void EvaMain::initGroups()
{
	std::list<std::string> names = user->getGroupNames();
	std::list<std::string>::iterator iter;
	int i=0;
	for(iter = names.begin(); iter!= names.end(); ++iter){
		QString g = codec->toUnicode(iter->c_str());
		mainWin->addGroup(g, i++);
	}
	QString gQun = codec->toUnicode(user->getQunGroupName().c_str());
	QString gAnonyms = codec->toUnicode(user->getAnonymousGroupName().c_str());
	QString gBlack = codec->toUnicode(user->getBlackGroupName().c_str());
	mainWin->addGroup(gQun, user->getQunIndex());
	mainWin->addGroup(gAnonyms, user->getAnonymousIndex());
	mainWin->addGroup(gBlack, user->getBlackIndex());
}

void EvaMain::slotGetOnlineStatus()
{
	std::map<int, QQFriend>::iterator iter;
	std::map<int, QQFriend> list = (user->getFriendList()).getAllFriendsMap();
	for(iter = list.begin(); iter != list.end(); ++iter){
		switch(iter->second.getStatus()){
		case QQ_FRIEND_STATUS_ONLINE:
			mainWin->changeToOnline(iter->second.getQQ());
			break;
		case QQ_FRIEND_STATUS_OFFLINE:
			mainWin->changeToOffline(iter->second.getQQ());
			break;
		case QQ_FRIEND_STATUS_LEAVE:
			mainWin->changeToLeave(iter->second.getQQ());
			break;
		case QQ_FRIEND_STATUS_INVISIBLE:
			mainWin->changeToInvisible(iter->second.getQQ());
			break;
		}	
	}	
}

void EvaMain::slotDoLoginClick()
{
	if(mainWin) mainWin->offline();
	if(tray) tray->reset();
	numLoginRetry = 0;
	isClientSet = false;
	slotFetchQQServer();
}

void EvaMain::slotFetchQQServer()
{
	EvaServers *server = global->getEvaServers();
	QObject::connect(server, SIGNAL(isReady(QHostAddress)), SLOT(slotGotServer(QHostAddress)));
	server->fetchAddress(loginWin->getConnectionType() == EvaLoginWindow::UDP ? true: false);
}

void EvaMain::slotGotServer(QHostAddress addr)
{
	printf("Got server :%s\n", addr.toString().ascii());
	QQServer = addr;
	if(!isClientSet)
		slotSetupEvaClient();
	slotDoLogin();
}

void EvaMain::slotServerBusy()
{
	if(numLoginRetry > MaxRetryTimes){
		slotPacketException( QQ_CMD_LOGIN);
	}else
		slotFetchQQServer();
}

void EvaMain::slotSetupEvaClient()
{
	if(loggedIn) slotDoLogout();
	if(packetManager) {
		delete packetManager;
	}
	if(windowList) delete windowList;
	
	mainWin->clearList();
	loginWin->hide();

	if(user){
		QObject::disconnect(user, 0, 0, 0);
	}
	
	user = new EvaUser(loginWin->getQQ(),loginWin->getMd5Password());
	
	QObject::connect(user, SIGNAL(loadGroupedBuddiesReady()), SLOT(slotLoadGroupedBuddiesReady()));
	QObject::connect(user, SIGNAL(loadQunListReady()), SLOT(slotLoadQunListReady()));
	QObject::connect(user->loginManager(), SIGNAL(processReady()), SLOT(slotLoginProcessReady()));
	QString qname, aname, bname;
	qname = i18n("Qun List");
	aname = i18n("Anonymous");
	bname = i18n("Black List");
	user->setQunGroupName(codec->fromUnicode(qname).data());
	user->setAnonymousGroupName(codec->fromUnicode(aname).data());
	user->setBlackGroupName(codec->fromUnicode(bname).data());
	user->getSetting()->loadSettings();
	images->setThemePath(user->getSetting()->getThemeDir());
	global->getSoundResource()->setSoundDir(user->getSetting()->getSoundDir());
	global->setFaceSize(QSize(user->getSetting()->getFaceSize()));
	
	slotUpdateShortcut();
	
	if(loginWin->isHiddenLoginMode())
		user->setStatus(EvaUser::Eva_Invisible);
	else
		user->setStatus(EvaUser::Eva_Online);
	
	QString nick = codec->toUnicode(user->getDetails().at(ContactInfo::Info_nick).c_str());// if not exist, default "EVA" will be used	
	QString name = i18n("Buddy");
	user->newGroup(codec->fromUnicode(name).data()); // we must do this if cannot load from disk

	
	if(picManager)
		delete picManager;
		
	if(uhManager){
		uhManager->stop();
		uhManager->wait();
		delete uhManager;
	}
	uhManager = new EvaUHManager(this, user->getSetting()->getUserHeadDir());
	uhManager->initiate();// load user head pictures
	if(images){
		images->setUserHeadImage(uhManager->getOnList(), uhManager->getOffList());
	}
	EvaNetwork *network = NULL;
	switch(loginWin->getConnectionType()){
	case EvaLoginWindow::UDP:
		network = new EvaNetwork(QQServer, 8000, EvaNetwork::UDP);
		picManager = new EvaPicManager(user);
		break;
	case EvaLoginWindow::TCP:
		network = new EvaNetwork(QQServer, 80, EvaNetwork::TCP);
		printf("connecting to \"%s\"\n", QQServer.toString().ascii());
		picManager = new EvaPicManager(user);
		break;
	case EvaLoginWindow::HTTP_Proxy:
		network = new EvaNetwork(QHostAddress(loginWin->getProxyIP()), loginWin->getProxyPort(), EvaNetwork::HTTP_Proxy);
		network->setDestinationServer(QQServer.toString(), 443);
		network->setAuthParameter(loginWin->getProxyParam());
		
		picManager = new EvaPicManager(user, true);
		picManager->setProxyServer(loginWin->getProxyIP(), loginWin->getProxyPort(), loginWin->getProxyParam());
		break;
	}
	
	connecter = new EvaConnecter(network);
	QObject::connect(connecter, SIGNAL(isReady()), SLOT(slotConnectReady()));
	packetManager = new EvaPacketManager(user, connecter);
	QObject::connect(packetManager, SIGNAL(networkException(int)), this, SLOT(slotNetworkException(int)));
	QObject::connect(packetManager, SIGNAL(packetException(int)), this, SLOT(slotPacketException(int)));
	QObject::connect(packetManager, SIGNAL(serverBusy()), SLOT(slotServerBusy()));
	QObject::connect(packetManager, SIGNAL(wrongPassword(QString)), SLOT(slotWrongPassword(QString)));
	QObject::connect(packetManager, SIGNAL(kickedOut(const QString)), SLOT(slotKickedOut(const QString)));
		
	QObject::connect(packetManager, SIGNAL(loginOK()), SLOT(slotLoginOK()));
	QObject::connect(packetManager, SIGNAL(onlineReady()), SLOT(slotOnlineReady()));
	QObject::connect(packetManager, SIGNAL(offlineReady()), SLOT(slotOfflineReady()));
	QObject::connect(packetManager, SIGNAL(invisibleReady()), SLOT(slotInvisibleReady()));
	QObject::connect(packetManager, SIGNAL(leaveReady()), SLOT(slotLeaveReady()));	
	QObject::connect(packetManager, SIGNAL(friendStatusChanged(int)), SLOT(slotFriendStatusChanged(int)));	
	QObject::connect(packetManager, SIGNAL(friendListReady()), SLOT(slotFriendListReady()));
	QObject::connect(packetManager, SIGNAL(deleteMeReady(bool)), SLOT(slotDeleteMeReply( bool )));
	QObject::connect(packetManager, 
			SIGNAL(txtMessage(int, bool, QString, QDateTime, const char,const bool, const bool, const bool, 
				const char , const char, const char)), 
			SLOT(slotTxtMessage(int, bool, QString, QDateTime, const char,const bool, const bool, const bool, 
				const char , const char, const char)));
	QObject::connect(packetManager, SIGNAL(qunTxtMessage(int, int, QString, QDateTime, const char , 
			const bool, const bool, const bool, const char, const char, const char)), 
			SLOT(slotReceivedQunMessage( int, int, QString, QDateTime, const char, 
			const bool, const bool, const bool, const char, const char, const char)));
	QObject::connect(packetManager, SIGNAL(friendGroupsReady()), SLOT(slotFriendGroupsReady()));
	QObject::connect(packetManager, SIGNAL(friendGroupsUploadReady(bool)), SLOT(slotFriendGroupsUploadReady(bool)));
	QObject::connect(packetManager, SIGNAL(deleteBuddyReady(int, bool)), SLOT(slotDeleteBuddyReady(int, bool)));		

	QObject::connect(packetManager, SIGNAL(myInfoReady()), SLOT(slotMyInfoReady()));
	QObject::connect(packetManager, SIGNAL(addBuddyReady()), SLOT(slotFriendListReady( )));
	QObject::connect(packetManager, SIGNAL(systemAddRequestApproved(int)), SLOT(slotFriendListReady( )));	

	QObject::connect(packetManager, SIGNAL(systemMeBeenAdded(int)), SLOT(slotSystemMeBeenAdded(int)));
	QObject::connect(packetManager, SIGNAL(systemAddMeRequest(int, QString)), SLOT(slotSystemAddMeRequest(int, QString)));
	QObject::connect(packetManager, SIGNAL(systemAddRequestApproved(int)), SLOT(slotSystemAddRequestApproved(int)));
	QObject::connect(packetManager, SIGNAL(systemAddRequestRejected(int, QString)), SLOT(slotSystemAddRequestRejected(int, QString)));
				
	QObject::connect(packetManager, SIGNAL(systemMeBeenAdded(int)), tray, SLOT(newSysMessage()));
	QObject::connect(packetManager, SIGNAL(systemAddMeRequest(int, QString)), tray, SLOT(newSysMessage()));
	QObject::connect(packetManager, SIGNAL(systemAddRequestApproved(int)), tray, SLOT(newSysMessage()));
	QObject::connect(packetManager, SIGNAL(systemAddRequestRejected(int, QString)), tray, SLOT(newSysMessage()));
	QObject::connect(packetManager, SIGNAL(qunSystemMessageRequest(const int, QString)), tray, SLOT(newSysMessage()));
	
	QObject::connect(packetManager, SIGNAL(qunInfomationReady(const int, const bool, QString)), 
					SLOT(slotQunInfomationReady(const int, const bool, QString)));
	QObject::connect(packetManager, SIGNAL(qunSystemMessageRequest(const int, QString)), 
					SLOT(slotQunSystemMessageRequest(const int, QString)));
	QObject::connect(packetManager, SIGNAL(qunRequestUpdateDisplay()), this, SLOT(slotLoadQunListReady()));
	QObject::connect(packetManager, SIGNAL(qunRequestQunCardReply(const int, const bool, const int, QString, const unsigned char, 
						QString, QString, QString, QString)), this,
			SLOT(slotRequestQunCardReady(const int, const bool, const int, QString, const unsigned char, 
						QString, QString, QString, QString)));
	QObject::connect(packetManager, SIGNAL(friendSignatureChanged(const int, const QDateTime, const QString)), 
			SLOT(slotFriendSignatureChanged(const int, const QDateTime, const QString)));
	QObject::connect(packetManager, SIGNAL(addAnonymous(const int, const short)), SLOT(slotAddAnonymous(const int, const short)));
						
	if(user->getSetting()->isShowSystemBroadcastEnabled())
		QObject::connect(packetManager, SIGNAL(systemNotification(int, QString)), tray, SLOT(newSysMessage()));
	
	
	windowList = new EvaChatWindowManager(images, user->getSetting(), nick, user->getQQ());
	QObject::connect(packetManager, SIGNAL(txtMessage(int, bool, QString, QDateTime, const char, 
			const bool, const bool, const bool, const char , const char, const char)), windowList, 
			SLOT(slotReceivedMessage(int, bool, QString, QDateTime, const char,const bool, const bool, const bool, 
			const char , const char, const char)));
	QObject::connect(packetManager, SIGNAL(sentMessageResult(int, bool)), windowList, SLOT(slotSendResult(int, bool)));
	QObject::connect(windowList, SIGNAL(requestQunCard(const int, const int)), packetManager, SLOT(doRequestQunCard( const int,  const int)));
	QObject::connect(windowList, SIGNAL(requestDetails(const int)), this, SLOT(slotRequestDetails(const int)));	
	QObject::connect(windowList, SIGNAL(sendMessage(const int , const bool , QString &, const char , 
			const bool , const bool , const bool , 
			const char, const char , const char)), packetManager, 
			SLOT(doSendMessage(const int , const bool  , QString &, const char, 
			const bool , const bool , const bool , 
			const char , const char, const char)));	
	QObject::connect(windowList, SIGNAL(requestHistory(const int)), this, SLOT(slotRequestHistory(const int)));	
	QObject::connect(windowList, SIGNAL(requestBuddyQQShow(const int)), this, SLOT(slotRequestQQShow(const int)));	
	QObject::connect(windowList, SIGNAL(requestMyQQShow()), this, SLOT(slotRequestMyQQShow()));
	
	// connect Qun stuff
	QObject::connect(packetManager, SIGNAL(qunTxtMessage(int, int, QString, QDateTime, const char , 
			const bool, const bool, const bool, const char, const char, const char)), windowList, 
			SLOT(slotReceivedQunMessage( int, int, QString, QDateTime, const char, 
				const bool, const bool, const bool, const char, const char, const char)));
	QObject::connect(packetManager, SIGNAL(qunSentMessageResult(int, bool, QString)), windowList, SLOT(slotQunSendResult(int, bool, QString)));
	QObject::connect(windowList, SIGNAL(requestQunDetails(const int)), this, SLOT(slotRequestQunDetails(const int)));
	QObject::connect(windowList, SIGNAL(sendQunMessage(const int, QString &, const char , 
			const bool, const bool, const bool, 
			const char, const char, const char)), packetManager, 
			SLOT(doSendQunMessage(const int, QString &, const char, 
			const bool , const bool, const bool , const char , const char , const char )));
	QObject::connect(windowList, SIGNAL(requestQunHistory(const int)), this, SLOT(slotRequestQunHistory(const int)));
	QObject::connect(windowList, SIGNAL(requestQunOnlineList(const int)), packetManager, 
			SLOT(doRequestQunOnlineMembers(const int)));
	QObject::connect(windowList, SIGNAL(requestQunMembers(const int)), this, SLOT(slotRequestQunMembers(const int)));
	QObject::connect(packetManager, SIGNAL(qunOnlineListReady(const int)), windowList, SLOT(slotQunOnlineMembers(const int)));
	QObject::connect(packetManager, SIGNAL(qunMemberInfoReady(const int)), windowList, 
			SLOT(slotQunMemberInfoReady( const int)));
			
	QObject::connect(picManager, SIGNAL(pictureReady(const int, const QString, const QString)), windowList,
			SLOT(slotQunPicReady(const int, const QString, const QString)));
	QObject::connect(picManager, SIGNAL(pictureSent(const int, const unsigned int, const unsigned int, const unsigned short)), windowList, 
			SLOT(slotQunPicSent(const int, const unsigned int, const unsigned int, const unsigned short)));
	QObject::connect(picManager, SIGNAL(sendErrorMessage(const int, const QString)), windowList, 
			SLOT(slotSendImageError(const int, const QString)));
	
	QObject::connect(packetManager, SIGNAL(qunExitReply(const int, const bool, QString)), this, 
			SLOT(slotQunExitReply( const int , const bool, QString)));
	
	QObject::connect(packetManager, SIGNAL(extraInfoReady()), this, SLOT(slotExtraInfoReady()));
	
	initGroups();
	user->loadGroupedBuddyList();
	user->loadQunList();
	tray->show();
	mainWin->show();
	isClientSet = true;
}

void EvaMain::slotDoLogin()
{
	tray->setLoginWaiting();
	connecter->redirectTo(QQServer.toIPv4Address(), -1);
}

void EvaMain::slotDoCancel()
{
	if(loginWin->isVisible())
		loginWin->hide();
	if(!mainWin->isVisible() && !isClientSet )
		doQuit();
	else{
		if(!tray->isVisible())
			tray->show();
		if(!mainWin->isVisible())
			mainWin->show();
	}
}

void EvaMain::slotConnectReady( )
{
	packetManager->doLogin();
}

void EvaMain::slotLoginOK( )
{
	QHostAddress addr;
	addr.setAddress(loginWin->getProxyIP());
	sysSetting->saveSetting(loginWin->getQQ(), loginWin->getMd5Password(),
					loginWin->isRememberChecked(), loginWin->isHiddenLoginMode(),  
					(int)loginWin->getConnectionType(),
					addr.toIPv4Address(), loginWin->getProxyPort(), loginWin->getProxyUserName(),
					loginWin->getProxyParam());
	initUserLeaveMenu();
	switch(user->getStatus()){
	case EvaUser::Eva_Online:
		mainWin->online();
		tray->setOnline();
		break;
	case EvaUser::Eva_Offline:
		mainWin->offline();
		tray->setOffline();
		break;
	case EvaUser::Eva_Leave:
		mainWin->leave();
		tray->setLeave();
		break;
	case EvaUser::Eva_Invisible:
		mainWin->invisible();
		tray->setInvisible();
	}

	packetManager->doGetUserInfo(user->getQQ());
	
	loggedIn = true;
	QTimer::singleShot(5000,this, SLOT(slotGetOnlineStatus()));
}

void EvaMain::slotOfflineReady()
{ 
	mainWin->offline();
	tray->setOffline();
	loggedIn = false;
	user->loginManager()->reset();
	user->loginManager()->finishedCommand(QQ_CMD_REQUEST_LOGIN_TOKEN);
	picManager->stop();
	if(onlineFriendTimer->isActive())
		onlineFriendTimer->stop();
}

void EvaMain::slotOnlineReady( )
{
	mainWin->online();
	tray->setOnline();
}

void EvaMain::slotInvisibleReady( )
{
	mainWin->invisible();
	tray->setInvisible();
}

void EvaMain::slotLeaveReady( )
{
	mainWin->leave();
	tray->setLeave();
}

void EvaMain::slotNetworkException( int exp)
{
	printf("network exception -- number:%d\n", exp);
	mainWin->offline();
	tray->setOffline();
	numOfLostKeepAlivePackets++; 
	if(onlineFriendTimer->isActive())
		onlineFriendTimer->stop();
	packetManager->doLogout();
	loggedIn = false;
	KMessageBox::information(0, i18n("Network error occurred, check your network then try Eva later please."),
				i18n("Network"));
}

void EvaMain::slotPacketException( int cmd)
{
	printf("packet exception -- commend code: 0x%4x\n", cmd);
	if(cmd == QQ_CMD_KEEP_ALIVE){
		if(numOfLostKeepAlivePackets < 1)
			numOfLostKeepAlivePackets++; 
			
	}
	if(!loggedIn && cmd == QQ_CMD_LOGIN || cmd == QQ_CMD_REQUEST_LOGIN_TOKEN){
		mainWin->offline();
		tray->setOffline();
		packetManager->doLogout();
		KMessageBox::information(0, i18n("Cannot login, try later please."), i18n("Eva Login"));
		loggedIn = false;
	}
	
	if(numOfLostKeepAlivePackets>=1){
		mainWin->offline();
		tray->setOffline();
		packetManager->doLogout();
		numOfLostKeepAlivePackets = 0;
		if(onlineFriendTimer->isActive())
			onlineFriendTimer->stop();
		KMessageBox::information(0, i18n("Lost connection with server, try later please."), i18n("Eva Connection"));
		loggedIn = false;
	}
}

void EvaMain::slotWrongPassword( QString msg)
{
	mainWin->offline();
	tray->setOffline();
	loggedIn = false;
	user->setStatus(EvaUser::Eva_Offline);
	numOfLostKeepAlivePackets = 0;
	KMessageBox::information(mainWin, msg, i18n("Eva Login"));
	slotDoChangeUser();
}

void EvaMain::slotKickedOut(const QString msg)
{
	mainWin->offline();
	tray->setOffline();
	loggedIn = false;
	user->setStatus(EvaUser::Eva_Offline);
	numOfLostKeepAlivePackets = 0;
	KMessageBox::error(mainWin, msg, i18n("Eva Login"));
}

void EvaMain::slotFriendListReady( )
{	
	mainWin->setFaceSize(global->getFaceSize());
	
	std::map<int, QQFriend>::iterator iter;
	std::map<int, QQFriend> list = (user->getFriendList()).getAllFriendsMap();
	QString nick;
	QString signature;
	int faceID;
	QPixmap *pixOn, *pixOff;
	for(iter = list.begin(); iter != list.end(); ++iter){
		nick = EvaTextFilter::filter(codec->toUnicode(iter->second.getNick().c_str()));
		signature = codec->toUnicode(iter->second.getSignature().c_str());
		
		faceID = (iter->second.getFace())/3 + 1;
		if(faceID<1) faceID = 1;
		pixOn = images->getFace(faceID, true);
		pixOff = images->getFace(faceID, false);
		if(iter->second.hasUserHead()){
			QPixmap *uhPic = images->getUserHeadPixmap(iter->second.getQQ());
			QPixmap *uhPicOff = images->getUserHeadPixmap(iter->second.getQQ(), true);
			if(uhPic) pixOn = uhPic;
			if(uhPicOff) pixOff = uhPicOff;
		}
		EvaBuddyItem::Status buddyStatus = EvaBuddyItem::Offline;
		switch(iter->second.getStatus()){
		case QQ_FRIEND_STATUS_ONLINE:
			buddyStatus = EvaBuddyItem::Online;
			break;
		case QQ_FRIEND_STATUS_OFFLINE:
			buddyStatus = EvaBuddyItem::Offline;
			break;
		case QQ_FRIEND_STATUS_LEAVE:
			buddyStatus = EvaBuddyItem::Leave;
			break;
		case QQ_FRIEND_STATUS_INVISIBLE:
			buddyStatus = EvaBuddyItem::Invisible;
			break;
		}
		mainWin->addBuddy(nick, iter->second.getQQ(), signature, iter->second.getGroupIndex(), 
				pixOn, pixOff, buddyStatus);
	}
	mainWin->updateAllGroupTitles();
	if(!user->isBuddiesLoaded()){
		user->saveGroupedBuddyList();
		user->setBuddyLoadedEnabled(true);
		slotDoDownloadGroups();
	}
	if(user->getSetting()->isShowOnlineEnabled())
		mainWin->slotShowOnlineBuddies();
	else
		mainWin->slotShowAllBuddies();
	user->loginManager()->finishedCommand(QQ_CMD_GET_FRIEND_LIST);
	if(!onlineFriendTimer->isActive())
		onlineFriendTimer->start(60000, false);
}

void EvaMain::slotFriendStatusChanged( int id )
{
	const QQFriend *frd = (user->getFriendList()).getFriend(id);
	if(frd){
		switch(frd->getStatus()){
		case QQ_FRIEND_STATUS_ONLINE:
			mainWin->changeToOnline(id);
			if(user->getSetting()->isShowBudyOnlineNotifyEnabled()){
				EvaTipWindow *tip = new EvaTipWindow(images, codec->toUnicode(frd->getNick().c_str()), 
									id, frd->getFace(), i18n("I am online."));
				QObject::connect(tip, SIGNAL(requestChat(const int)), SLOT(slotRequestChat(const int)));
				if(user->getSetting()->isSoundEnabled())
					global->getSoundResource()->playOnlineSound();
			}
			break;
		case QQ_FRIEND_STATUS_OFFLINE:
			mainWin->changeToOffline(id);
			break;
		case QQ_FRIEND_STATUS_LEAVE:
			mainWin->changeToLeave(id);
			if(user->getSetting()->isShowBudyOnlineNotifyEnabled()){
				EvaTipWindow *tip = new EvaTipWindow(images, codec->toUnicode(frd->getNick().c_str()), 
									id, frd->getFace(), i18n("I am busy ..."));
				QObject::connect(tip, SIGNAL(requestChat(const int)), SLOT(slotRequestChat(const int)));
			}
			break;
		case QQ_FRIEND_STATUS_INVISIBLE:
			mainWin->changeToInvisible(id);
			break;
		}
	}else{
		printf("buddy %d not in list\n", id);
	}
}

void EvaMain::slotTxtMessage(int sender, bool, QString message, QDateTime, const char, 
			const bool, const bool, const bool, 
			const char, const char, const char)
{
	QString reply="";
	if(user->getStatus() == EvaUser::Eva_Leave && user->getSetting()->isAutoReplyEnabled()){
		reply = user->getSetting()->getSelectedAutoReply();
		packetManager->doSendMessage(sender, false, reply, 9, false, false, false, 0,0,0);
	}
	if(!(windowList && windowList->isChatWindowExisted(sender))){	
		mainWin->newMessage(sender);
		const QQFriend *frd = (user->getFriendList()).getFriend(sender);
		short faceId = 0x0000;
		if(frd)
			faceId = frd->getFace();
		tray->newTxtMessage(sender, faceId);
		if(user->getSetting()->isShowMessageTipEnabled()){
			EvaTipWindow *tip = new EvaTipWindow(images, codec->toUnicode(frd->getNick().c_str()), sender, faceId, message);
			QObject::connect(tip, SIGNAL(requestChat(const int)), SLOT(slotRequestChat(const int)));
		}
	}
	if(user->getSetting()->isSoundEnabled())
		global->getSoundResource()->playNewMessage();
}

void EvaMain::slotFriendGroupsReady( )
{
	mainWin->clearList();
	initGroups();
	slotFriendListReady();
	QunList *qunList = user->getQunList();
	if(qunList && qunList->numQuns()){
		std::list<Qun>::iterator iter;
		std::list<Qun> list = qunList->getQunList();
		for(iter=list.begin(); iter!=list.end(); ++iter){
			QunInfo info = iter->getDetails();
			QString name = "";
			if(!info.getQunID())
				name = QString::number(iter->getQunID());
			else
				name = EvaTextFilter::filter(codec->toUnicode(info.getName().c_str()));
			mainWin->addQun(name, iter->getQunID(), images->getIcon("QUN"));
		}
		
	}
	if(!user->isBuddiesLoaded()){
		user->saveGroupedBuddyList();
		user->setBuddyLoadedEnabled(true);
	}
	std::list<int>msgs = windowList->getMessages();
	std::list<int>::iterator itr;
	for(itr = msgs.begin(); itr != msgs.end(); ++itr){
		mainWin->newMessage(*itr);
	}
}

void EvaMain::slotDoOnline()
{
	if(user->getStatus() == EvaUser::Eva_Offline){
		user->setStatus(EvaUser::Eva_Online);
		user->loginManager()->finishedCommand(QQ_CMD_GET_FRIEND_LIST);
		slotDoLogin();
	}else
		packetManager->doChangeStatus(EvaUser::Eva_Online);
}

void EvaMain::slotDoOffline()
{
	packetManager->doChangeStatus(EvaUser::Eva_Offline);
}

void EvaMain::slotDoLeave()
{
	if(user->getStatus() == EvaUser::Eva_Offline){
		user->setStatus(EvaUser::Eva_Leave);
		user->loginManager()->finishedCommand(QQ_CMD_GET_FRIEND_LIST);
		slotDoLogin();
	}else
		packetManager->doChangeStatus(EvaUser::Eva_Leave);
}

void EvaMain::slotDoInvisible()
{
	if(user->getStatus() == EvaUser::Eva_Offline){
		user->setStatus(EvaUser::Eva_Invisible);
		user->loginManager()->finishedCommand(QQ_CMD_GET_FRIEND_LIST);
		slotDoLogin();
	}else
		packetManager->doChangeStatus(EvaUser::Eva_Invisible);
}

void EvaMain::slotDoLogout()
{
	if(onlineFriendTimer->isActive())
		onlineFriendTimer->stop();
	packetManager->doLogout();
	loggedIn = false;
	user->loginManager()->reset();
}

void EvaMain::slotDoDownloadGroups()
{
	user->setBuddyLoadedEnabled(false);
	packetManager->doGetGroups();
}

void EvaMain::slotDoUploadGroups()
{
	packetManager->doUploadGroups();
}

void EvaMain::slotFriendGroupsUploadReady(bool ok)
{
	if(ok)
		KMessageBox::information(mainWin, i18n("Uploading grouped friends successfully."), i18n("Eva Upload Groups"));
	else
		KMessageBox::information(mainWin, i18n("Uploading grouped friends failed."), i18n("Eva Upload Groups"));
}

void EvaMain::slotDoDownloadBuddies()
{
	user->setBuddyLoadedEnabled(false);
	user->loginManager()->clearCommandFlag(QQ_CMD_GET_FRIEND_LIST);
	packetManager->doGetAllFriends();
}

void EvaMain::slotDoChangeUser()
{
	if(mainWin->isVisible())
		mainWin->hide();
	if(tray->isVisible())
		tray->hide();
	if(!loginWin->isVisible())
		loginWin->show();
}

void EvaMain::slotGroupDeleted( const int index)
{
	user->removeGroupName(index);
	user->saveGroupedBuddyList();
}

void EvaMain::slotGroupAdded( QString gn, int index)
{
	std::string name = (codec->fromUnicode(gn)).data();
	user->newGroup(name);
	int newIndex = user->getGroupIndexOf(name);
	mainWin->listView->findGroup(index)->setGroupIndex(newIndex);
	user->saveGroupedBuddyList();
}

void EvaMain::slotGroupRenamed( QString gn, int index)
{
	std::string name = (codec->fromUnicode(gn)).data();
	user->updateGroupName(name, index);
	user->saveGroupedBuddyList();
}

void EvaMain::slotGroupChanged(int id, int index)
{
	user->getFriendList().updateFriendGroupIndex(id, index);
	user->saveGroupedBuddyList();
}

void EvaMain::slotRequestDetails(const int id)
{	
	QStringList details;
	details.append(QString::number(id));
	
	const QQFriend *frd = (user->getFriendList()).getFriend(id); 
	if(frd){
		std::string qq = frd->getUserInformation().at(0);
		if(qq!="-")
			details = packetManager->convertDetails(frd->getUserInformation());
	}
		
	EvaDetailsWindow *detailWin;
	if(id == user->getQQ()){
		if(user->getDetails().at(0)!="-")
			details = packetManager->convertDetails(user->getDetails());
		detailWin = new EvaDetailsWindow(details,true);
		QObject::connect(detailWin, SIGNAL(requestModify(QStringList, QString, QString)), 
					packetManager, SLOT(doModifyDetails(QStringList, QString, QString)));	
		QObject::connect(packetManager, SIGNAL(modifyInfo(bool)), 
					detailWin, SLOT(slotUpdateResult(bool)));
	}else{
		detailWin = new EvaDetailsWindow(details,false);
	}	
	QObject::connect(detailWin, SIGNAL(requestUpdate(const int)), packetManager, SLOT(doGetUserInfo(const int)));
	QObject::connect(detailWin, SIGNAL(requestQQshow(const int)), this, SLOT(slotRequestQQShow(const int)));
	QObject::connect(detailWin, SIGNAL(requestUpdateSignature(const QString)), packetManager, 
			SLOT(doModifySignature( const QString))); 
	QObject::connect(detailWin, SIGNAL(requestDeleteSignature()), packetManager, 
			SLOT(doDeleteSignature())); 
	
	QObject::connect(packetManager, SIGNAL(signatureModifyReply(const bool)), detailWin, SLOT(slotSignatureReply(const bool)));
	QObject::connect(packetManager, SIGNAL(signatureDeleteReply(const bool)), detailWin, SLOT(slotSignatureReply(const bool)));
	QObject::connect(packetManager, SIGNAL(userInfoReady(QStringList)), detailWin, SLOT(slotDetailsUpdated(QStringList)));
	QObject::connect(images, SIGNAL(qqShowReady(const int)), detailWin, SLOT(slotBuddyQQShowReady(const int)));
	detailWin->show();
}

void EvaMain::slotRequestChat(const int id)
{
	const QQFriend *frd = user->getFriendList().getFriend(id);
	mainWin->gotMessage(id);
	tray->gotTxtMessage(id);
	windowList->openChatWindow(frd);
}

void EvaMain::slotRequestLevel(const int id)
{
	if(loggedIn)
		packetManager->requestFriendLevel(id);
}

void EvaMain::slotRequestHistory(const int id)
{
	QString nick = codec->toUnicode(user->getFriendList().getFriend(id)->getNick().c_str());
	
	EvaChatWindow *win = windowList->getWindow(id);
	EvaHistoryViewer *viewer = new EvaHistoryViewer(id, nick, user->getSetting());
	
	int faceId = atoi(user->getDetails().at(ContactInfo::Info_face).c_str());
	QPixmap *face = images->getFace(images->getFaceFileIndex(faceId));
	viewer->setIcon(*face);
	
	if(win){
		QObject::connect(viewer, SIGNAL(historyDoubleClicked(int, QString, int, QString, bool,
					 QString, QDateTime, const char, 
					const bool, const bool, const bool, 
					const char, const char, const char)), 
				win, 
				SLOT(slotAddMessage(int, QString, int, QString, bool,
					 QString, QDateTime, const char, 
					const bool, const bool, const bool, 
					const char, const char, const char)));
		viewer->move(win->x(), win->y() + win->height() + 25);
	}else{
		QRect scr = KApplication::desktop()->screenGeometry();    
		viewer->move(scr.center() - viewer->rect().center());
	}
	viewer->show();
}

void EvaMain::slotRequestQQShow(const int id)
{
	images->requestQQShow(id);
}

void EvaMain::slotRequestMyQQShow()
{
	slotRequestQQShow(user->getQQ());
}

void EvaMain::slotQQShowReady( const int id)
{
	if(id == user->getQQ())
		windowList->slotMyQQShowReady();
	else
		windowList->slotBuddyQQShowReady(id);
}

void EvaMain::slotRequestSearch( )
{
	EvaSearchWindow *win = new EvaSearchWindow(images, packetManager->getNumOnlineUsers(), 0, "Searching");
	QObject::connect(win, SIGNAL(requestSearchUsers(const bool, const QString, const QString, const QString, const QString, const bool)),
			 packetManager, 
			 SLOT(doSearchUsers(const bool, const QString, const QString, const QString, const QString, const bool)));
	QObject::connect(win, SIGNAL(requestUserInfo(const int)), this, SLOT(slotRequestDetails(const int)));
	QObject::connect(win, SIGNAL(requestAddAuthBuddy(const int, const QString &)), 
			packetManager, 
			SLOT(doAddAuthBuddy(const int , const QString &)));
	QObject::connect(win, SIGNAL(requestAddBuddy(const int)), packetManager, SLOT(doAddBuddy(const int)));
	QObject::connect(win, SIGNAL(requestSearchQun(const int)), packetManager, SLOT(doSearchQun(const int)));
	QObject::connect(win, SIGNAL(requestJoinQun(const int)), packetManager, SLOT(doJoinQun(const int)));
	QObject::connect(win, SIGNAL(requestJoinQunAuth(const int, const QString &)), packetManager, SLOT(doJoinQunAuth(const int, const QString &)));
	
	QObject::connect(packetManager, SIGNAL(searchUsersReady(const bool, const std::list<OnlineUser>)), win, 
			SLOT(slotSearchUsersReady(const bool, const std::list<OnlineUser>)));
	QObject::connect(packetManager, SIGNAL(addBuddyReady()), win, SLOT(slotAddBuddyReady()));
	QObject::connect(packetManager, SIGNAL(addBuddyRejected()), win, SLOT(slotAddBuddyRejected()));
	QObject::connect(packetManager, SIGNAL(addBuddyNeedAuth()), win, SLOT(slotBuddyNeedAuth()));
	QObject::connect(packetManager, SIGNAL(addBuddySentToServer(bool)), win, SLOT(slotAddBuddySentToServer(bool)));
	QObject::connect(packetManager, SIGNAL(qunSearchReady(const std::list<QunInfo>, QString)), 
			win, SLOT(slotQunSearchReady(const std::list<QunInfo>, QString)));
	QObject::connect(packetManager, SIGNAL(qunJoinReplyOK(const int)), win, SLOT(slotQunJoinReplyOK(const int)));
	QObject::connect(packetManager, SIGNAL(qunJoinReplyNeedAuth(const int)), win, SLOT(slotQunJoinReplyNeedAuth(const int)));
	QObject::connect(packetManager, SIGNAL(qunJoinReplyDenied(const int)), win, SLOT(slotQunJoinReplyDenied(const int)));
	QObject::connect(packetManager, SIGNAL(qunJoinAuthReply(const int)), win, SLOT(slotQunJoinAuthReply(const int)));
	
	QRect scr = KApplication::desktop()->screenGeometry();    
	win->move(scr.center() - win->rect().center());	
	win->show();
}

void EvaMain::slotSystemMeBeenAdded(int)
{
	if(user->getSetting()->isSoundEnabled())
		global->getSoundResource()->playSysMessage();
}

void EvaMain::slotSystemAddMeRequest(int, QString)
{
	if(user->getSetting()->isSoundEnabled())
		global->getSoundResource()->playSysMessage();
}

void EvaMain::slotSystemAddRequestApproved(int)
{
	if(user->getSetting()->isSoundEnabled())
		global->getSoundResource()->playSysMessage();
}

void EvaMain::slotSystemAddRequestRejected(int, QString)
{
	if(user->getSetting()->isSoundEnabled())
		global->getSoundResource()->playSysMessage();
}

void EvaMain::slotRequestSystemMessage( )
{
	EvaUserSetting::sysMessage m = user->getSetting()->getLastSysMessage();
	if(m.type == 0 && m.from == 0) return;
	slotShowSystemMessage( m.messageType, m.type, m.from, m.to, m.message, m.internalQunID);
}

void EvaMain::slotShowSystemMessage(const short msgType, const uint8_t type, const int from, const int to, 
					const QString message, const int internalQunID)
{	
	EvaNotifyWindow *win = new EvaNotifyWindow(0);
	if(msgType == SYSTEM_MESSAGE_NORMAL){
		switch(type){
		case 200:
			win->slotAddBuddy(from);
		case QQ_MSG_SYS_BEING_ADDED:
			win->slotMeBeenAdded( from);
			break;       
		case QQ_MSG_SYS_ADD_FRIEND_REQUEST:
			win->slotAddMeRequest(from, message);
			break;
		case QQ_MSG_SYS_ADD_FRIEND_APPROVED:
			win->slotAddRequestApproved(from);
			break;
		case QQ_MSG_SYS_ADD_FRIEND_REJECTED:
			win->slotAddRequestRejected(from, message);
			break;
		default:
			if(user->getSetting()->isShowSystemBroadcastEnabled())
				win->slotOtherNotification(from, message);
		}
		QObject::connect(win, SIGNAL(requestUserInfo(const int)), this, SLOT(slotRequestDetails(const int)));
		QObject::connect(win, SIGNAL(requestAddAuthBuddy(const int, const QString &)), 
				packetManager, SLOT(doAddAuthBuddy(const int, const QString &)));
		QObject::connect(win, SIGNAL(requestAddBuddy(const int)), packetManager, SLOT(doAddBuddy(const int)));
		QObject::connect(win, SIGNAL(requestApproveBuddy(const int)), packetManager, SLOT(doApproveBuddy(const int)));
		QObject::connect(win, SIGNAL(requestRejectBuddy(const int, const QString &)), 
				packetManager, SLOT(doRejectBuddy(const int, const QString &)));
		
		QObject::connect(packetManager, SIGNAL(addBuddyReady()), win, SLOT(slotAddBuddyReady()));
		QObject::connect(packetManager, SIGNAL(addBuddyRejected()), win, SLOT(slotAddBuddyRejected()));
		QObject::connect(packetManager, SIGNAL(addBuddyNeedAuth()), win, SLOT(slotBuddyNeedAuth()));
		QObject::connect(packetManager, SIGNAL(addBuddySentToServer(bool)), win, SLOT(slotAddBuddySentToServer(bool)));
		
		QObject::connect(packetManager, SIGNAL(systemMeBeenAdded(int)), win, SLOT(slotMeBeenAdded(int)));
		QObject::connect(packetManager, SIGNAL(systemAddMeRequest(int, QString)), win, SLOT(slotAddMeRequest(int, QString)));
		QObject::connect(packetManager, SIGNAL(systemAddRequestApproved(int)), win, SLOT(slotAddRequestApproved(int)));
		QObject::connect(packetManager, SIGNAL(systemAddRequestRejected(int, QString)), win, SLOT(slotAddRequestRejected(int, QString)));
	}else{ // now should be Qun messages
		switch(msgType){
		case QQ_RECV_IM_CREATE_QUN:
			win->slotQunCreated(from, to, internalQunID);
			break;
		case QQ_RECV_IM_ADDED_TO_QUN:
			win->slotQunAdded(from, to, internalQunID);
			break;       
		case QQ_RECV_IM_DELETED_FROM_QUN:
			win->slotQunRemoved(from, to, internalQunID);
			break;
		case QQ_RECV_IM_REQUEST_JOIN_QUN:
			win->slotQunJoinRequest(from, to, message, internalQunID);
			break;
		case QQ_RECV_IM_APPROVE_JOIN_QUN:
			win->slotQunRequestApproved(from, to, message, internalQunID);
			break;
		case QQ_RECV_IM_REJECT_JOIN_QUN:
			win->slotQunRequestRejected(from, to, message, internalQunID);
			break;
		}
		QObject::connect(win, SIGNAL(requestUserInfo(const int)), this, SLOT(slotRequestDetails(const int)));
		QObject::connect(win, SIGNAL(requestApproveQun(const int, const int)), packetManager, SLOT(doApproveQun(const int, const int)));
		QObject::connect(win, SIGNAL(requestRejectQun(const int, const int, const QString &)), 
				packetManager, SLOT(doRejectQun(const int,const int, const QString &)));
		QObject::connect(packetManager, SIGNAL(qunJoinAuthReply(const int)), win, SLOT(slotQunJoinAuthReply(const int)));
	}
	if(user->getSetting()->isShowSystemBroadcastEnabled())
		QObject::connect(packetManager, SIGNAL(systemNotification(int, QString)), win, SLOT(slotOtherNotification(int, QString)));
	QRect scr = KApplication::desktop()->screenGeometry();    
	win->move(scr.center() - win->rect().center());
	win->show();
}


void EvaMain::slotRequestSystemMessages( )
{
	EvaSysHistoryViewer *viewer = new EvaSysHistoryViewer( user->getSetting());
	QObject::connect(viewer, SIGNAL(historyDoubleClicked(const short , const uint8_t, const int, const int, const QString, const int)), 
			SLOT(slotShowSystemMessage(const short ,const uint8_t, const int, const int, const QString, const int)));
	
	QRect scr = KApplication::desktop()->screenGeometry();    
	viewer->move(scr.center() - viewer->rect().center());
	viewer->show();
}

void EvaMain::slotRequestDelete( const int id)
{
	packetManager->doDeleteBuddy(id);
}

void EvaMain::slotDeleteBuddyReady( int id, bool ok)
{
	if(ok)
		mainWin->deleteBuddy(id);
	else{
		KMessageBox::information(mainWin, QString(i18n("Delete buddy \"%1\" failed.")).arg(id), i18n("Eva Delete Buddy"));
	}
}

void EvaMain::slotRequestSystemSettingWindow( )
{
	EvaSysSettingWindow *win = new EvaSysSettingWindow(images, user->getSetting(), mainWin);
	QObject::connect(win, SIGNAL(settingChanged()), SLOT(slotUserSettingChanged()));
	QRect scr = KApplication::desktop()->screenGeometry();    
	win->move(scr.center() - win->rect().center());	
	win->show();
}

void EvaMain::slotDeleteMeFrom( int id)
{
	if(deleteFromQQ != -1) return;  // make sure we only delete from one friend's list at a moment
	const QQFriend *frd = user->getFriendList().getFriend(id);
	if(!frd) return;
	QString nick = codec->toUnicode(frd->getNick().c_str());
	if(KMessageBox::warningYesNo( mainWin, QString(i18n("put \"%1\" into Blacklist, are you sure?")).arg(nick),
			i18n( "Eva Blacklist")) == KMessageBox::No)
		return;
	deleteFromQQ = id;
	packetManager->doDeleteMeFrom(id);
}

void EvaMain::slotDeleteMeReply( bool ok)
{
	if(ok){
		mainWin->changeGroupTo(deleteFromQQ, user->getBlackIndex());
		slotGroupChanged(deleteFromQQ, user->getBlackIndex());
		deleteFromQQ = -1;
	}else
		KMessageBox::information(mainWin, QString(i18n("Blacklist operation on \"%1\" failed.")).arg(deleteFromQQ),
				i18n("Eva Blacklist"));
}

void EvaMain::slotRequestAddBuddy(const int id)
{
	if(KMessageBox::warningYesNo( mainWin,
		QString(i18n("add \"%1\" into your Buddy list?")).arg(id), i18n( "Eva Add Buddy")) == KMessageBox::No)
		return;
		
	slotShowSystemMessage(SYSTEM_MESSAGE_NORMAL, 200, id, id,"");
}

void EvaMain::slotMyInfoReady( )
{	
	QString myNick = codec->toUnicode(user->getDetails().at(ContactInfo::Info_nick).c_str()); 
	mainWin->setCaption(myNick + " - Eva");
	int myFaceId = atoi(user->getDetails().at(ContactInfo::Info_face).c_str());
	QPixmap *face = images->getFace(images->getFaceFileIndex(myFaceId));
	if(user->hasUserHead()){
		QPixmap *uhPic = images->getUserHeadPixmap(user->getQQ()); // color pixmap
		if(uhPic) face = uhPic;
	}
	mainWin->setIcon(*face);
	mainWin->setMainInfo(user->getQQ(), myNick, face?face:images->getFace(0)); 
	windowList->setMyName(myNick, user->getQQ());
	
	if(!user->isBuddiesLoaded())
		slotDoDownloadBuddies();
}

void EvaMain::slotQunInfomationReady(int id, const bool /*ok*/, QString /*errorMsg*/)
{
	const Qun *qun = user->getQunList()->getQun(id);
	user->saveQunList();
	if(qun){
		QunInfo info = qun->getDetails();
		QString name = codec->toUnicode(info.getName().c_str());
		mainWin->updateQun(name, id, images->getIcon("QUN"));
	}
}

void EvaMain::slotRequestQunDetails( const int id)
{
	Qun *qun = user->getQunList()->getQun(id);
	QunDetailsWindow *win = new QunDetailsWindow(qun);
	QObject::connect(win, SIGNAL(requestQunInfo(const int)), 
			packetManager, SLOT(doRequestQunInfo(const int)));
	QObject::connect(packetManager, SIGNAL(qunInfomationReady(const int, const bool, QString)), 
			win, SLOT(slotQunInfomationReady(const int, const bool, QString)));
	
	QObject::connect(win, SIGNAL(requestModifyQunInfo(const int, unsigned char, unsigned short, QString, QString, QString)), 
			packetManager, SLOT(doModifyQunInfo(const int, unsigned char, unsigned short, QString, QString, QString)));
	QObject::connect(packetManager, SIGNAL(qunModifyInfoReply(const int, const bool, QString)), 
					win, SLOT(slotModifyQunInfo(const int, const bool, QString)));
					
	QObject::connect(win, SIGNAL(requestModifyQunCard(const int, const int, QString, unsigned char, QString, QString, QString)), 
			packetManager, SLOT(doModifyQunCard(const int,  const int, QString, unsigned char, QString, QString, QString)));
	QObject::connect(packetManager, SIGNAL(qunModifyQunCardReply(const int, const bool, const int, QString)), 
			win, SLOT(slotModifyQunCardReply( const int, const bool, const int, QString)));
			
	QObject::connect(win, SIGNAL(requestQunSetAdmin(const int, const int, const bool)), 
			packetManager, SLOT(doQunSetAdmin(const int, const int, const bool)));
	QObject::connect(packetManager, SIGNAL(qunSetAdminReply(const int , const bool , const int, const bool , QString)), 
			win, SLOT(slotSetAdmin(const int, const bool, const int, const bool, QString)));

	QObject::connect(win, SIGNAL(requestQunTransfer(const int, const int)), 
			packetManager, SLOT(doQunTransfer(const int, const int)));
	QObject::connect(packetManager, SIGNAL(qunTransferReply(const int , const bool, const int, QString)), 
			win, SLOT(slotTransferQun(const int, const bool, const int, QString)));
			
	QObject::connect(win, SIGNAL(requestModifyQunMembers(const int, const std::list<int>, const bool)), 
			packetManager, SLOT(doModifyQunMembers(const int, const std::list<int>, const bool)));
	QObject::connect(packetManager, SIGNAL(qunModifyQunMembersReply(const int, const bool, QString)), 
			win, SLOT(slotModifyQunMembers(const int, const bool, QString)));

	QObject::connect(win, SIGNAL(requestAddBuddy(const int)), SLOT(slotRequestAddBuddy(const int)));
	
	QObject::connect(packetManager, SIGNAL(qunMemberInfoReady(const int)), 
			win, SLOT(slotMembersUpdated(const int)));
			
	QObject::connect(win, SIGNAL(requestUpdateQunMessageSettings(const int, const signed char)), 
				SLOT(slotUpdateQunMessageSettings(const int, const signed char)));
	QRect scr = KApplication::desktop()->screenGeometry();    
	win->move(scr.center() - win->rect().center());
	win->show();
}

void EvaMain::slotRequestQunCardReady(const int id, const bool ok, const int qq, QString realName, const unsigned char gender, 
					QString phone, QString email, QString memo, QString msg)
{
	Qun *qun = user->getQunList()->getQun(id);
	QunDetailsWindow *win = new QunDetailsWindow(qun);
	win->slotReceivedQunCard(id, ok, qq, realName, gender, phone, email, memo, msg);
	
	QObject::connect(win, SIGNAL(requestQunInfo(const int)), 
			packetManager, SLOT(doRequestQunInfo(const int)));
	QObject::connect(packetManager, SIGNAL(qunInfomationReady(const int, const bool, QString)), 
			win, SLOT(slotQunInfomationReady(const int, const bool, QString)));
	
	QObject::connect(win, SIGNAL(requestModifyQunInfo(const int, unsigned char, unsigned short, QString, QString, QString)), 
			packetManager, SLOT(doModifyQunInfo(const int, unsigned char, unsigned short, QString, QString, QString)));
	QObject::connect(packetManager, SIGNAL(qunModifyInfoReply(const int, const bool, QString)), 
					win, SLOT(slotModifyQunInfo(const int, const bool, QString)));
					
	QObject::connect(win, SIGNAL(requestModifyQunCard(const int, const int, QString, unsigned char, QString, QString, QString)), 
			packetManager, SLOT(doModifyQunCard(const int,  const int, QString, unsigned char, QString, QString, QString)));
	QObject::connect(packetManager, SIGNAL(qunModifyQunCardReply(const int, const bool, const int, QString)), 
			win, SLOT(slotModifyQunCardReply( const int, const bool, const int, QString)));
			
	QObject::connect(win, SIGNAL(requestQunSetAdmin(const int, const int, const bool)), 
			packetManager, SLOT(doQunSetAdmin(const int, const int, const bool)));
	QObject::connect(packetManager, SIGNAL(qunSetAdminReply(const int , const bool , const int, const bool , QString)), 
			win, SLOT(slotSetAdmin(const int, const bool, const int, const bool, QString)));

	QObject::connect(win, SIGNAL(requestQunTransfer(const int, const int)), 
			packetManager, SLOT(doQunTransfer(const int, const int)));
	QObject::connect(packetManager, SIGNAL(qunTransferReply(const int , const bool, const int, QString)), 
			win, SLOT(slotTransferQun(const int, const bool, const int, QString)));
			
	QObject::connect(win, SIGNAL(requestModifyQunMembers(const int, const std::list<int>, const bool)), 
			packetManager, SLOT(doModifyQunMembers(const int, const std::list<int>, const bool)));
	QObject::connect(packetManager, SIGNAL(qunModifyQunMembersReply(const int, const bool, QString)), 
			win, SLOT(slotModifyQunMembers(const int, const bool, QString)));
	
	QObject::connect(win, SIGNAL(requestAddBuddy(const int)), SLOT(slotRequestAddBuddy(const int)));
	QObject::connect(packetManager, SIGNAL(qunMemberInfoReady(const int)), 
		win, SLOT(slotMembersUpdated(const int)));
	
	QObject::connect(win, SIGNAL(requestUpdateQunMessageSettings(const int, const signed char)), 
				SLOT(slotUpdateQunMessageSettings( const int, const signed char)));
	QRect scr = KApplication::desktop()->screenGeometry();    
	win->move(scr.center() - win->rect().center());
	win->show();
}

void EvaMain::slotRequestQunHistory( const int id)
{
	Qun *qun = user->getQunList()->getQun(id);
	QString qName = i18n("Qun");
	if(qun){
		QunInfo info = qun->getDetails();
		qName = codec->toUnicode(info.getName().c_str());
	}
	
	EvaQunChatWindow *win = windowList->getQunWindow(id);
	EvaHistoryViewer *viewer = new EvaHistoryViewer(id, qName, user->getSetting(), true);
	
	int faceId = atoi(user->getDetails().at(ContactInfo::Info_face).c_str());
	QPixmap *face = images->getFace(images->getFaceFileIndex(faceId));
	viewer->setIcon(*face);
	
	if(win){
		QObject::connect(viewer, SIGNAL(historyDoubleClicked(int, QString, int, QString, bool,
					 QString, QDateTime, const char, 
					const bool, const bool, const bool, 
					const char, const char, const char)), 
				win, 
				SLOT(slotAddMessage(int, QString, int, QString, bool,
					 QString, QDateTime, const char, 
					const bool, const bool, const bool, 
					const char, const char, const char)));
		viewer->move(win->x(), win->y() + win->height() + 25);
	}else{
		QRect scr = KApplication::desktop()->screenGeometry();    
		viewer->move(scr.center() - viewer->rect().center());
	}
	viewer->show();
}

void EvaMain::slotRequestQunChat( const int id)
{
	Qun *qun = user->getQunList()->getQun(id);
	if(!qun) return;
	mainWin->gotQunMessage(id);
	tray->gotTxtMessage(id);
	windowList->openQunChatWindow(qun);
}

void EvaMain::slotReceivedQunMessage( int qunID, int senderQQ, QString /*msg*/, QDateTime /*time*/, const char /*fontSize*/, 
				const bool /*u*/, const bool /*i*/, const bool /*b*/, const char /*blue*/, const char /*green*/, const char /*red*/)
{
	//note that: Qun never show tip
	Qun *qun = user->getQunList()->getQun(qunID);
	if(!qun) return;
	if(senderQQ == user->getQQ()) return;
	if(!(windowList && windowList->isQunChatWindowExisted(qunID))){
		if(qun->getMessageType() == Qun::Popup){
			slotRequestQunChat(qunID);
		}else if(qun->getMessageType() == Qun::Numbers){
			mainWin->newQunMessage(qunID);
		}else{
			mainWin->newQunMessage(qunID);
			tray->newTxtMessage(qunID, -2); // -2 means qun message;
		}
	}
	if(user->getSetting()->isSoundEnabled())
		global->getSoundResource()->playNewMessage();
}

void EvaMain::slotQunSystemMessageRequest( const int /*sender*/, QString /*message*/)
{
	if(user->getSetting()->isSoundEnabled())
		global->getSoundResource()->playSysMessage();
}

void EvaMain::slotQunPictureReady( const int id, const QString fileName , const QString tmpFileName)
{
	windowList->slotQunPicReady(id, fileName, tmpFileName);
}

void EvaMain::slotShotcutKeyPressed( )
{
	if(!tray) return;
	int id = tray->getSenderID();
	
	const QQFriend *frd = user->getFriendList().getFriend(id);
	if(frd){
		mainWin->gotMessage(id);
		tray->gotTxtMessage(id);
		windowList->openChatWindow(frd);
		return;
	}
	
	Qun *qun = user->getQunList()->getQun(id);
	if(qun){
		mainWin->gotQunMessage(id);
		tray->gotTxtMessage(id);
		windowList->openQunChatWindow(qun);
		return;
	}
	EvaUserSetting::sysMessage m = user->getSetting()->getLastSysMessage();
	if(!(m.type == 0 && m.from == 0)){
		slotShowSystemMessage( m.messageType, m.type, m.from, m.to, m.message, m.internalQunID);
		return;
	}	
	
	if(!mainWin->isVisible()) mainWin->show();
	else
		KWin::forceActiveWindow(mainWin->winId());
}

void EvaMain::slotQunExitReply( const int id, const bool ok, QString msg)
{
	QString qunName;
	Qun *qun = user->getQunList()->getQun(id);
	if(!qun) qunName = QString::number(id);
	else
		qunName = codec->toUnicode(qun->getDetails().getName().c_str());
	
	QString desc;
	if(ok)
		desc = QString(i18n("You have exited the Qun \"%1\" successfully.")).arg(qunName);
	else
		desc = QString(i18n("Exit Qun \"%1\" failed\n%2")).arg(qunName).arg(msg);
	
	KMessageBox::information( mainWin, desc, i18n("Qun Operation"));
}

void EvaMain::slotDoQunExit( const int id )
{
	QString qunName;
	Qun *qun = user->getQunList()->getQun(id);
	if(!qun) qunName = QString::number(id);
	else
		qunName = codec->toUnicode(qun->getDetails().getName().c_str());
	
	QunInfo info = qun->getDetails();
	QString msg;
	if(info.getExtID() != 0 && info.getCreator() == user->getQQ()){
		msg = QString(i18n("You are the creator of Qun \"%1\", if you exit this Qun this Qun will be deleted, are you sure?")).arg(qunName);
	}else{
		msg = QString(i18n("Are you sure you want to exit Qun \"%1\"?")).arg(qunName);
	}
	if(KMessageBox::questionYesNo(mainWin, msg, i18n("Qun Operation")) != KMessageBox::No)
		packetManager->doQunExit(id);
}

void EvaMain::slotQunCreateFailed(QString msg)
{
	KMessageBox::information(mainWin, msg, i18n("Qun Operation"));
}

void EvaMain::slotQunCreate( )
{
	EvaQunCreateWindow *win = new EvaQunCreateWindow();
	QObject::connect(win, SIGNAL(doQunCreate(const QString &, const unsigned short, const unsigned char, const QString &, 
					const QString &, const std::list<int> &)), 
		packetManager, SLOT(doQunCreate(const QString &, const unsigned short, const unsigned char, const QString &, 
					const QString &, const std::list<int> &)));
	QObject::connect(packetManager, SIGNAL(qunCreateDone(const int)), win, SLOT(slotQunCreateDone(const int)));
	QObject::connect(packetManager, SIGNAL(qunCreateFailed(QString)), win, SLOT(slotQunCreateFailed(QString)));
	win->show();
}

void EvaMain::slotFriendSignatureChanged( const int qq, const QDateTime /*time*/, const QString signature )
{
	
	const QQFriend *frd = (user->getFriendList()).getFriend(qq);
	if(frd){
		if(mainWin) mainWin->updateSignature(qq, signature);
		QString nick = codec->toUnicode(frd->getNick().c_str());
		QString title = nick + "(<font color=red>" + i18n("signature") + "</font>)";
		EvaTipWindow *tip = new EvaTipWindow(images, title, qq, frd->getFace(), signature);
		QObject::connect(tip, SIGNAL(requestChat(const int)), SLOT(slotRequestChat(const int)));
	}else{
		printf("buddy %d not in list\n", qq);
	}	
}

/** we simply request the qun information which will update all details */
void EvaMain::slotRequestQunMembers( const int id)
{
	packetManager->doRequestQunInfo(id);
}

void EvaMain::slotUpdateQunMessageSettings( const int id, const signed char type )
{
	Qun *qun = user->getQunList()->getQun(id);
	if(!qun) return;
	qun->setMessageType((Qun::MessageType)type);
	printf("EvaMain::slotUpdateQunMessageSettings -- qun messageType: %d\n", 0xff&type);
	user->saveQunList();
}

void EvaMain::slotUpdateShortcut( )
{
	if(accelKey) delete accelKey;
	accelKey  = new KGlobalAccel(this, "Eva Short Key");
	accelKey->insert("Eva Global Key", i18n("Eva Global Key"), 
			i18n("This action allows you to read your new Eva message globally."),
			user->getSetting()->getMessageShortcut(), KKey::QtWIN+Key_F12, this, SLOT(slotShotcutKeyPressed( )));
	if(!accelKey->updateConnections())
		printf("F12 Key registered failed!");
}

void EvaMain::slotUserSettingChanged( )
{
	slotUpdateShortcut();
	global->setFaceSize(QSize(user->getSetting()->getFaceSize()));
	QString newSoundDir=user->getSetting()->getSoundDir();
	if(!newSoundDir.isEmpty()){
		global->getSoundResource()->setSoundDir(newSoundDir);
	}
	mainWin->clearList();
	initGroups();
	slotFriendListReady();
	slotLoadQunListReady();
	initUserLeaveMenu();
}

void EvaMain::slotLoginProcessReady( )
{
	printf("user login process done!\n");
	packetManager->lastLoginStep();
	connecter->clientReady();
}

void EvaMain::slotAddAnonymous(const int id, const short face)
{
	if(mainWin){
		QString nick = QString::number(id);
		mainWin->addBuddy(nick, (int)id, QString(""), EvaUser::getAnonymousIndex(),
				images->getFace(face, true), images->getFace(face, false));
	}
}

void EvaMain::slotExtraInfoReady( )
{
	if(uhManager){
		uhManager->stop();
		uhManager->wait();
		delete uhManager;
		uhManager = NULL;
	}
	
	uhManager = new EvaUHManager(this, user->getSetting()->getUserHeadDir());
	uhManager->initiate();
	
	std::list<int> list = user->getFriendList().getUserHeadList(user->getQQ(), user->hasUserHead());
	if(list.size()){
		uhManager->setQQList(list);
		uhManager->start();
	}
	
}

void EvaMain::customEvent( QCustomEvent * e )
{
	if(e->type() == EvaUserHeadReadyEvent){
		EvaUHReadyEvent *event = (EvaUHReadyEvent *)e;
		int id = event->getQQ();
		QImage imgOn = event->getOnImage();
		QImage imgOff = event->getOffImage();
		if(images){
			images->addUserHeadImage(id, imgOn, imgOff);
			printf("EvaMain::customEvent -- images->addUserHeadImage\n");
			if(id == user->getQQ()){
				slotMyInfoReady( );
			}
			mainWin->updateFacePixmaps(id, images->getUserHeadPixmap(id),  // color pixmap
						images->getUserHeadPixmap(id, true)); // grayscale pixmap
		}
	}
}

void EvaMain::slotShowOnlineSelected( )
{
	user->getSetting()->setShowOnlineEnabled(true);
	user->getSetting()->saveSettings();
}

void EvaMain::slotShowAllSelected( )
{
	user->getSetting()->setShowOnlineEnabled(false);
	user->getSetting()->saveSettings();
}
