//=============================================================================
//
//   File : kvi_frame.cpp
//   Creation date : Sun Jun 18 2000 17:59:02 by Szymon Stefanek
//
//   This file is part of the KVirc irc client distribution
//   Copyright (C) 1999-2000 Szymon Stefanek (pragma at kvirc dot net)
//
//   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 opinion) 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. ,51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
//=============================================================================

#define __KVIRC__
#define _KVI_FRAME_CPP_

#include "kvi_debug.h"
#include "kvi_app.h"
#include "kvi_settings.h"
#include "kvi_frame.h"
#include "kvi_options.h"
#include "kvi_menubar.h"
#include "kvi_mdimanager.h"
#include "kvi_mdichild.h"
#include "kvi_iconmanager.h"
#include "kvi_window.h"
#include "kvi_taskbar.h"
#include "kvi_console.h"
#include "kvi_config.h"
#include "kvi_internalcmd.h"
#include "kvi_console.h"
#include "kvi_debug.h"
#include "kvi_irctoolbar.h"
#include "kvi_confignames.h"
#include "kvi_parameterlist.h"
#include "kvi_module.h"
#include "kvi_mextoolbar.h"
#include "kvi_locale.h"
#include "kvi_irccontext.h"
#include "kvi_statusbar.h"
#include "kvi_customtoolbar.h"
#include "kvi_customtoolbarmanager.h"
#include "kvi_customtoolbardescriptor.h"
#include "kvi_actionmanager.h"
#include "kvi_defaults.h"
#include "kvi_ircview.h"
#include "kvi_tal_popupmenu.h"

#include "kvi_kvs_script.h"
#include "kvi_kvs_eventtriggers.h"

#include <tqsplitter.h>
#include <tqvariant.h>
#include <tqlineedit.h>
#include <tqmessagebox.h>
#include <tqcheckbox.h>

#include <tqtimer.h>
#include <tqlayout.h>

#include <tqfile.h>
#include <tqtextstream.h>
	#include <tqdockarea.h>


	#include <tqaccel.h>

#include <time.h>

#ifdef COMPILE_PSEUDO_TRANSPARENCY
	#include <tqpixmap.h>
	// kvi_app.h
	extern TQPixmap * g_pShadedParentGlobalDesktopBackground;
	extern TQPixmap * g_pShadedChildGlobalDesktopBackground;
// FIXME: #warning "When a toolbar is moved , MdiManager is resized but does not update the MdiChild backgrounds"
#endif

// Declared and managed by KviApp (kvi_app.cpp)
extern KviConfig * g_pWinPropertiesConfig;
KVIRC_API KviFrame * g_pFrame = 0; // the one and only frame object

KviFrame::KviFrame()
: KviTalMainWindow(0,"kvirc_frame")
{
	g_pFrame = this;

	setIcon(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_KVIRC)));

	m_pWinList  = new KviPointerList<KviWindow>;
	m_pWinList->setAutoDelete(false);

	m_pModuleExtensionToolBarList = new KviPointerList<KviMexToolBar>;
	m_pModuleExtensionToolBarList->setAutoDelete(false);

	m_pActiveContext = 0;

	m_pDockExtension = 0;

	m_pSplitter = new TQSplitter(TQt::Horizontal,this,"main_splitter");
//	m_pSplitter->setFrameShape(TQFrame::NoFrame);

	setCentralWidget(m_pSplitter);

	setUsesBigPixmaps(KVI_OPTION_BOOL(KviOption_boolUseBigIcons));

	m_pMdi      = new KviMdiManager(m_pSplitter,this,"mdi_manager");
	connect(m_pMdi,TQ_SIGNAL(enteredSdiMode()),this,TQ_SLOT(enteredSdiMode()));
	connect(m_pMdi,TQ_SIGNAL(leftSdiMode()),this,TQ_SLOT(leftSdiMode()));

	// This theoretically had to exists before KviMdiManager (that uses enterSdiMode)
	m_pMenuBar   = new KviMenuBar(this,"main_menu_bar");

	if(KVI_OPTION_BOOL(KviOption_boolStatusBarVisible))
	{
		m_pStatusBar = new KviStatusBar(this);
		// torque: moved out of status bar constructor
		// because module init functions exectued in load()
		// couldn't access the status bar via g_pFrame->mainStatusBar()
		// (assignment of m_pStatusBar happened after load() and
		// the init function)
		m_pStatusBar->load();

	} else
		m_pStatusBar = 0;

	m_pTaskBar = 0;

	createTaskBar();

	if((KVI_OPTION_RECT(KviOption_rectFrameGeometry).width() < 100) || (KVI_OPTION_RECT(KviOption_rectFrameGeometry).height() < 100))
	{
		// Try to find some reasonable defaults
		KVI_OPTION_RECT(KviOption_rectFrameGeometry) = TQRect(10,10,g_pApp->desktop()->width() - 200,g_pApp->desktop()->height() - 150);
	}

	resize(KVI_OPTION_RECT(KviOption_rectFrameGeometry).width(),
		KVI_OPTION_RECT(KviOption_rectFrameGeometry).height());
	move(KVI_OPTION_RECT(KviOption_rectFrameGeometry).x(),
		KVI_OPTION_RECT(KviOption_rectFrameGeometry).y());

	applyOptions();


	m_pAccel = new KviAccel(this);

	installAccelerators(this);

	layout()->setResizeMode(TQLayout::FreeResize);
}

KviFrame::~KviFrame()
{
	KVI_OPTION_RECT(KviOption_rectFrameGeometry) = TQRect(pos().x(),pos().y(),
			size().width(),size().height());

	KVI_OPTION_BOOL(KviOption_boolUseBigIcons) = usesBigPixmaps();
	KVI_OPTION_BOOL(KviOption_boolMdiManagerInSdiMode) = m_pMdi->isInSDIMode();
	KVI_OPTION_BOOL(KviOption_boolStatusBarVisible) = m_pStatusBar ? true : false;

	KviCustomToolBarManager::instance()->storeVisibilityState();

	saveToolBarPositions();
	saveModuleExtensionToolBars();

	// Call the frame destructor callback AFTER saving the toolbar positions
	// This is because the destructor callback kills alls the KVS objects
	// and thus the eventual user toolbar objects too and their position
	// wouldn't be saved if they are shown at startup.

	g_pApp->frameDestructorCallback();

	// Now start killing stuff

	// Explicitly kill all the module extension toolbars: tqt has NOT to delete them: we must call their "die" method
	while(KviMexToolBar * t = m_pModuleExtensionToolBarList->first())t->die();
	delete m_pModuleExtensionToolBarList;

	KVI_OPTION_BOOL(KviOption_boolShowDockExtension) = m_pDockExtension;

	if(m_pDockExtension)
	{
		m_pDockExtension->die();
		m_pDockExtension = 0;
	}

	// the really last thing to do : close all the windows
	while(m_pWinList->first())
		closeWindow(m_pWinList->first());
	delete m_pWinList;

	delete m_pAccel;
	g_pFrame = 0;
}

int KviFrame::registerAccelerator(const TQString &szKeySequence,TQObject * recv,const char * slot)
{
	int id = m_pAccel->insertItem(szKeySequence);
	m_pAccel->connectItem(id,recv,slot);
	return id;
}

void KviFrame::unregisterAccelerator(int id)
{
	m_pAccel->removeItem(id);
}

void KviFrame::registerModuleExtensionToolBar(KviMexToolBar * t)
{
	m_pModuleExtensionToolBarList->append(t);
}

void KviFrame::unregisterModuleExtensionToolBar(KviMexToolBar * t)
{
	m_pModuleExtensionToolBarList->removeRef(t);
}

void KviFrame::restoreModuleExtensionToolBars()
{
	for(TQStringList::Iterator it = KVI_OPTION_STRINGLIST(KviOption_stringlistModuleExtensionToolbars).begin();it != KVI_OPTION_STRINGLIST(KviOption_stringlistModuleExtensionToolbars).end();++it)
	{
		TQString szEntry = *it;
		int idx = szEntry.find(':');
		if(idx != -1)
		{
			TQString szMod = szEntry.left(idx);
			szEntry.remove(0,idx + 1);
			g_pModuleExtensionManager->allocateExtension("toolbar",KviStr(szEntry),firstConsole(),0,0,szMod);
		}
	}
}

void KviFrame::saveModuleExtensionToolBars()
{
	KVI_OPTION_STRINGLIST(KviOption_stringlistModuleExtensionToolbars).clear();

	for(KviMexToolBar * t = m_pModuleExtensionToolBarList->first();t;t = m_pModuleExtensionToolBarList->next())
	{
		TQString s = t->descriptor()->module()->name();
		s += ":";
		s += t->descriptor()->name().ptr();

		//tqDebug("FOUND TOOLBAR %s",t->descriptor()->name().ptr());

		KVI_OPTION_STRINGLIST(KviOption_stringlistModuleExtensionToolbars).append(s);
	}
}

KviMexToolBar * KviFrame::moduleExtensionToolBar(int extensionId)
{
	for(KviMexToolBar * t = m_pModuleExtensionToolBarList->first();t;t = m_pModuleExtensionToolBarList->next())
	{
		if(extensionId == t->descriptor()->id())return t;
	}
	return 0;
}

/*
	@doc: keyboard
	@type:
		generic
	@title:
		Keyboard shortcuts
	@keyterms:
		Keyboard shortcuts
	@short:
		The list of the common keyboard shortcuts
	@body:
		[b]Ctrl+LeftArrow[/b]: Selection left to the previous word[br]
		[b]Ctrl+RightArrow[/b]: Selection right to the next word[br]
		[b]Ctrl+Shift+LeftArrow[/b]: Previous word[br]
		[b]Ctrl+Shift+RightArrow[/b]: Next word[br]
		[b]Alt+LeftArrow[/b]: Previous window[br]
		[b]Alt+RightArrow[/b]: Next window[br]
		[b]Alt+Shift+LeftArrow[/b]: Previous window in the same IRC context[/b]
		[b]Alt+Shift+RightArrow[/b]: Next window in the same IRC context[/b]
		[b]Ctrl+UpArrow[/b]: Maximize current window[br]
		[b]Ctrl+DownArrow[/b] or [b]ESC[/b]: Minimize current window[br]
		[b]Ctrl+&lt;digit&gt;[/b], [b]F1-F12[/b], [b]Shift+(F1-F12)[/b]: Script accelerators (see [event:onaccelkeypressed]OnAccelKeyPressed[/event])[br]
		[b]Shift+&lt;F1-F12&gt;[/b] window switch[br]
		[b]Tab in the first word of input[/b]: Completes nicknames in the current channel or query[br]
		[b]Tab after a leading /[/b]: Completes commands[br]
		[b]Tab after a / in the middle of input[/b]: Completes directories[br]
		[b]Tab after a $[/b]: Completes function names[br]
		[b]Shift+Tab after the first word of input[/b]: completes masks in the current channel or query[br]
		[b]Ctrl+B[/b]: Inserts the 'bold' mIRC text control character[br]
		[b]Ctrl+K[/b]: Inserts the 'color' mIRC text control character[br]
		[b]Ctrl+R[/b]: Inserts the 'reverse' mIRC text control character[br]
		[b]Ctrl+U[/b]: Inserts the 'underline' mIRC text control character[br]
		[b]Ctrl+O[/b]: Inserts the 'reset' mIRC text control character[br]
		[b]Ctrl+P[/b]: Inserts the 'non-crypt' (plain text) KVIrc control character used to disable encryption of the current text line[br]
		[b]Ctrl+C[/b]: Copies the selected text to clipboard[br]
		[b]Ctrl+X[/b]: Cuts the selected text[br]
		[b]Ctrl+V[/b]: Pastes the clipboard contents (same as middle mouse click)[br]
		[b]Ctrl+I[/b]: Inserts the 'icon' control code and pops up the icon list box
		[b]CursorUp[/b]: Moves backward in the command history[br]
		[b]CursorDown[/b]: Moves forward in the command history[br]
		[b]Ctrl+PageUp[/b]: Opens the history popup[br]
		[b]CursorRight[/b]: Moves the cursor to the right[br]
		[b]CursorLeft[/b]: Moves the cursor to the left :)[br]
		[b]Shift+CursorLeft[/b]: Moves the selection to the left[br]
		[b]Shift+RightCursor[/b]: Moves the selection to the right[br]
		[b]PageUp[/b]: Scrolls the output window up one page[br]
		[b]PageDown[/b]: Scrolls the output window down one page[b]
		[b]Shift+PageUp[/b]: Scrolls the output window up one line[br]
		[b]Shift+PageDown[/b]: Scrolls the output window down one line[b]
		[b]Alt+lt;numeric_sequence&gt;[/b]: Inserts the character by ASCII/Unicode code[br]
		[b]Ctrl+Backspace[/b]: Shows or hides the multiline editor[br]
		[b]Ctrl+F4[/b]: Closes the current window[br]
		<example>
			Alt+32: Inserts ASCII/Unicode character 32: ' ' (a space)
			Alt+00032: Same as above :)
			Alt+13: Inserts the Carriage Return (CR) control character
			Alt+77: Inserts ASCII/Unicode character 77: 'M'
			Alt+23566: Inserts Unicode character 23566 (an ideogram)
		</example>
*/

KviAccel * KviFrame::installAccelerators(TQWidget * wnd)
{
	TQWidget * pParent = wnd ? (TQWidget *)wnd : (TQWidget *)this;
	KviAccel *ac = new KviAccel(pParent);

	static int accel_table[] = {
		TQt::Key_Left + TQt::ALT ,    // prev window
		TQt::Key_Right + TQt::ALT ,   // next window
		TQt::Key_Up + TQt::CTRL ,      // maximize window
		TQt::Key_Down + TQt::CTRL ,    // minimize window
		TQt::Key_Escape +TQt::CTRL,         // minimize window
		TQt::Key_Left + TQt::ALT + TQt::SHIFT ,  // prev window in context
		TQt::Key_Right + TQt::ALT + TQt::SHIFT,  // next window in context
		TQt::Key_F4 + TQt::CTRL ,     // close current window
		TQt::Key_1 + TQt::CTRL ,       // script accels...
		TQt::Key_2 + TQt::CTRL ,
		TQt::Key_3 + TQt::CTRL ,
		TQt::Key_4 + TQt::CTRL ,
		TQt::Key_5 + TQt::CTRL ,
		TQt::Key_6 + TQt::CTRL ,
		TQt::Key_7 + TQt::CTRL ,
		TQt::Key_8 + TQt::CTRL ,
		TQt::Key_9 + TQt::CTRL ,
		TQt::Key_0 + TQt::CTRL ,
		TQt::Key_F1 , // reserved for context sensitive help
		TQt::Key_F2 ,
		TQt::Key_F3 ,
		TQt::Key_F4 ,
		TQt::Key_F5 ,
		TQt::Key_F6 ,
		TQt::Key_F7 ,
		TQt::Key_F8 ,
		TQt::Key_F9 ,
		TQt::Key_F10 ,
		TQt::Key_F11 ,
		TQt::Key_F12 ,
/*		TQt::Key_F1 + TQt::SHIFT ,       // window select...
		TQt::Key_F2 + TQt::SHIFT ,
		TQt::Key_F3 + TQt::SHIFT ,
		TQt::Key_F4 + TQt::SHIFT ,
		TQt::Key_F5 + TQt::SHIFT ,
		TQt::Key_F6 + TQt::SHIFT ,
		TQt::Key_F7 + TQt::SHIFT ,
		TQt::Key_F8 + TQt::SHIFT ,
		TQt::Key_F9 + TQt::SHIFT ,
		TQt::Key_F10 + TQt::SHIFT ,
		TQt::Key_F11 + TQt::SHIFT ,
		TQt::Key_F12 + TQt::SHIFT ,*/
		0
	};

	int i=0;
	int keys;
	while((keys = accel_table[i]))
	{
		ac->insertItem(keys);
		i++;
	}

	connect(ac,TQ_SIGNAL(activated(int)),this,TQ_SLOT(accelActivated(int)));
	return ac;
}

void KviFrame::accelActivated(int id)
{
	KviAccel * acc = (KviAccel *)sender();

	int keys = (int)(acc->key(id));
	KviTaskBarItem *item = 0;
	tqDebug("accel");
	switch(keys)
	{
		case (TQt::Key_Left+TQt::ALT): switchToPrevWindow(); break;
		case (TQt::Key_Right+TQt::ALT): switchToNextWindow(); break;
		case (TQt::Key_Up+TQt::CTRL): maximizeWindow(); break;
		case (TQt::Key_Escape+TQt::CTRL):
		case (TQt::Key_Down+TQt::CTRL): minimizeWindow(); break;
		case (TQt::Key_Left+TQt::ALT+TQt::SHIFT): switchToPrevWindowInContext(); break;
		case (TQt::Key_Right+TQt::ALT+TQt::SHIFT): switchToNextWindowInContext(); break;
		case (TQt::Key_F4+TQt::CTRL):	if(g_pActiveWindow)g_pActiveWindow->close(); break;
		case (TQt::Key_F1): g_pApp->contextSensitiveHelp(); break;
/*		case(TQt::Key_F1 + SHIFT):
			item = m_pTaskBar->item(0);
			if(item) setActiveWindow(item->window());
			break;
		case(TQt::Key_F2 + SHIFT):
			item = m_pTaskBar->item(1);
			if(item) setActiveWindow(item->window());
			break;
		case(TQt::Key_F3 + SHIFT):
			item = m_pTaskBar->item(2);
			if(item) setActiveWindow(item->window());
			break;
		case(TQt::Key_F4 + SHIFT):
			item = m_pTaskBar->item(3);
			if(item) setActiveWindow(item->window());
			break;
		case(TQt::Key_F5 + SHIFT):
			item = m_pTaskBar->item(4);
			if(item) setActiveWindow(item->window());
			break;
		case(TQt::Key_F6 + SHIFT):
			item = m_pTaskBar->item(5);
			if(item) setActiveWindow(item->window());
			break;
		case(TQt::Key_F7 + SHIFT):
			item = m_pTaskBar->item(6);
			if(item) setActiveWindow(item->window());
			break;
		case(TQt::Key_F8 + SHIFT):
			item = m_pTaskBar->item(7);
			if(item) setActiveWindow(item->window());
			break;
		case(TQt::Key_F9 + SHIFT):
			item = m_pTaskBar->item(8);
			if(item) setActiveWindow(item->window());
			break;
		case(TQt::Key_F10 + SHIFT):
			item = m_pTaskBar->item(9);
			if(item) setActiveWindow(item->window());
			break;
		case(TQt::Key_F11 + SHIFT):
			item = m_pTaskBar->item(10);
			if(item) setActiveWindow(item->window());
			break;
		case(TQt::Key_F12 + SHIFT):
			item = m_pTaskBar->item(11);
			if(item) setActiveWindow(item->window());
			break;*/
		default:
		{
			KVS_TRIGGER_EVENT_1(KviEvent_OnAccelKeyPressed,g_pActiveWindow,(TQString)(acc->key(id)));
		}
		break;
	};
}

void KviFrame::executeInternalCommand(int index)
{
	KviKvsScript::run(kvi_getInternalCommandBuffer(index),firstConsole());
}


void KviFrame::saveWindowProperties(KviWindow * wnd,const TQString &szSection)
{
	g_pWinPropertiesConfig->setGroup(szSection);
	g_pWinPropertiesConfig->writeEntry("EntryTimestamp",(unsigned int)time(0));

	// Allow max 80 window properties to be floating around
	while(g_pWinPropertiesConfig->groupsCount() > 80)
	{
		// Kill the oldest group
		KviConfigIterator it(*(g_pWinPropertiesConfig->dict()));
		KviStr minKey;
		unsigned int minVal = time(0);
		while(it.current() && minVal)
		{
			TQString * pVal = it.current()->find("EntryTimestamp");
			if(pVal)
			{
				bool bOk;
				unsigned int uVal = pVal->toUInt(&bOk);
				if(bOk)
				{
					if(uVal < minVal)
					{
						minVal = uVal;
						minKey = it.currentKey();
					}
				} else {
					minVal = 0;
					minKey = it.currentKey();
				}
			} else {
				minVal = 0;
				minKey = it.currentKey();
			}
			++it;
		}

		if(minKey.hasData())g_pWinPropertiesConfig->clearGroup(minKey.ptr());
		else tqDebug("Oops...no minimum key found!");
	}

	// The following line should NOT be needed...but just to be sure...
	g_pWinPropertiesConfig->setGroup(szSection);

	g_pWinPropertiesConfig->writeEntry("IsDocked",wnd->mdiParent());

//	KviWindow * top = g_pActiveWindow;
//	if(!top)top = wnd;
//	g_pWinPropertiesConfig->writeEntry("IsMaximized",top->isMaximized());

	g_pWinPropertiesConfig->writeEntry("WinRect",wnd->externalGeometry());

	wnd->saveProperties(g_pWinPropertiesConfig);
}

void KviFrame::closeWindow(KviWindow *wnd)
{
	// notify the destruction
	wnd->triggerDestructionEvents();

	// save it's properties
	if(KVI_OPTION_BOOL(KviOption_boolWindowsRememberProperties)) // && (wnd->type() == KVI_WINDOW_TYPE_CHANNEL))
	{
		TQString group;
		wnd->getConfigGroupName(group);
		// not uses default settings : store it always
		saveWindowProperties(wnd,group);
	}

	// forget it...
	m_pWinList->removeRef(wnd);

	// hide it
	if(wnd->mdiParent())wnd->mdiParent()->hide();
	else wnd->hide();

	if(wnd == g_pActiveWindow)
	{
		// we need another active window before destroying it
		KviMdiChild * pMdiChild = wnd->mdiParent();
		if(pMdiChild)
		{
			pMdiChild = m_pMdi->highestChildExcluding(pMdiChild);
		} else {
			// the best candidate for the new active window
			// is the top mdiManager's child
			pMdiChild = m_pMdi->topChild();
		}
		KviWindow * pCandidate;
		if(pMdiChild)
		{
			pCandidate = (KviWindow *)(pMdiChild->client());
		} else {
			pCandidate = m_pWinList->first();
			if(pCandidate == wnd)pCandidate = 0;
		}

		if(pCandidate)
			childWindowActivated(pCandidate);
		// else { m_pActiveWindow = 0; m_pActiveContext = 0; };
	}

	if(wnd == g_pActiveWindow) // ops... :/ ... this happens only at shutdown
	{
		g_pActiveWindow = 0;
		m_pActiveContext = 0;
	}

	// and shut it down...
	// KviWindow will call childWindowDestroyed() here
	if(wnd->mdiParent())m_pMdi->destroyChild(wnd->mdiParent(),true);
	else delete wnd;
}


void KviFrame::addWindow(KviWindow *wnd,bool bShow)
{
	m_pWinList->append(wnd);
	wnd->createTaskBarItem(); // create the window taskbar item AFTER it has been constructed

	TQString group;
	wnd->getConfigGroupName(group);

	bool bGroupSettings = false;

	if(g_pWinPropertiesConfig->hasGroup(group))
	{
		g_pWinPropertiesConfig->setGroup(group);
	} else {
		bGroupSettings = true;
		if(g_pWinPropertiesConfig->hasGroup(wnd->typeString()))
		{
			g_pWinPropertiesConfig->setGroup(wnd->typeString());
		} else {
			g_pWinPropertiesConfig->setGroup("no_settings_group");
			wnd->loadProperties(g_pWinPropertiesConfig); // load it anyway (will set defaults if windows don't remember properties)
			goto default_docking; // no settings stored
		}
	}

	{
		wnd->loadProperties(g_pWinPropertiesConfig); // load it anyway (will set defaults if windows don't remember properties)

		if(KVI_OPTION_BOOL(KviOption_boolWindowsRememberProperties))
		{
			bool bDocked    = g_pWinPropertiesConfig->readBoolEntry("IsDocked",true);
			//bool bMaximized = g_pWinPropertiesConfig->readBoolEntry("IsMaximized",false);
			bool bMaximized;

			if(KVI_OPTION_BOOL(KviOption_boolMdiManagerInSdiMode))
			{
				bMaximized = true;
				//KVI_OPTION_BOOL(KviOption_boolMdiManagerInSdiMode) = false;
			} else bMaximized = false;

			TQRect rect      = g_pWinPropertiesConfig->readRectEntry("WinRect",TQRect(10,10,500,380));

			if(bDocked)
			{
				// when group settings are used , we always cascade the windows
				// this means that windows that have no specialized config group name
				// are always cascaded : this is true for consoles , queries (and other windows) but not channels (and some other windows)
				KviMdiChild * lpC = dockWindow(wnd,false,bGroupSettings,&rect);
				lpC->setRestoredGeometry(rect);
				wnd->triggerCreationEvents();
				if(bShow)
				{
					m_pMdi->showAndActivate(lpC);
					if(bMaximized)wnd->maximize();
					// Handle the special case of this top level widget not being the active one.
					// In this situation the child will not get the focusInEvent
					// and thus will not call out childWindowActivated() method
					if(!isActiveWindow())childWindowActivated(wnd);
				}
			} else {
				wnd->setGeometry(rect);
				wnd->triggerCreationEvents();
				if(bShow)
				{
					wnd->show();
					if(bMaximized)wnd->maximize();
				}
				wnd->youAreUndocked();
				if(bShow)
				{
					wnd->raise();
					wnd->setFocus();
				}
			}
			goto docking_done;
		}
	}

default_docking:
	{
		KviMdiChild * lpC = dockWindow(wnd,false); //cascade it
		wnd->triggerCreationEvents();
		if(bShow)
		{
			m_pMdi->showAndActivate(lpC);
			if(KVI_OPTION_BOOL(KviOption_boolMdiManagerInSdiMode)) wnd->maximize();
			// Handle the special case of this top level widget not being the active one.
			// In this situation the child will not get the focusInEvent
			// and thus will not call out childWindowActivated() method
			if(!isActiveWindow())childWindowActivated(wnd);
		}
	}
docking_done:
	// we like to have an active window.. but don't trigger the events until it is really shown
	if(!g_pActiveWindow)
	{
		g_pActiveWindow = wnd;
		m_pActiveContext = wnd->context();
	}
}

KviMdiChild * KviFrame::dockWindow(KviWindow *wnd,bool bShow,bool bCascade,TQRect *setGeom)
{
	if(wnd->mdiParent())return wnd->mdiParent();
	KviMdiChild * lpC = new KviMdiChild(m_pMdi,"");
	lpC->setClient(wnd);
	wnd->youAreDocked();
	m_pMdi->manageChild(lpC,bCascade,setGeom);
	if(bShow)m_pMdi->showAndActivate(lpC);
	return lpC;
}

void KviFrame::undockWindow(KviWindow *wnd)
{
	if(!(wnd->mdiParent()))return;
	KviMdiChild * lpC = wnd->mdiParent();
	lpC->unsetClient();
	m_pMdi->destroyChild(lpC,false);
	wnd->youAreUndocked();
	wnd->raise();
	wnd->setFocus();
}


void KviFrame::newConsole()
{
	createNewConsole();
}

KviConsole * KviFrame::createNewConsole(bool bFirstInFrame)
{
	// the first console must be created BEFORE the toolbars visible
	// at startup otherwise we cannot execute script code
	// which is necessary for the actions that are going to be added
	// to the toolbars
	KviConsole * c = new KviConsole(this,bFirstInFrame ? KVI_CONSOLE_FLAG_FIRSTINFRAME : 0);
	addWindow(c);

	if(bFirstInFrame)
	{
		restoreModuleExtensionToolBars();
		KviCustomToolBarManager::instance()->createToolBarsVisibleAtStartup();
		KviActionManager::instance()->delayedRegisterAccelerators();
		restoreToolBarPositions();
	}

	return c;
}

unsigned int KviFrame::consoleCount()
{
	unsigned int count = 0;
	for(KviWindow * wnd = m_pWinList->first();wnd;wnd = m_pWinList->next())
	{
		if(wnd->type() == KVI_WINDOW_TYPE_CONSOLE)count++;
	}
	return count;
}

KviConsole * KviFrame::firstConsole()
{
	for(KviWindow * wnd = m_pWinList->first();wnd;wnd = m_pWinList->next())
	{
		if(wnd->type() == KVI_WINDOW_TYPE_CONSOLE)return (KviConsole *)wnd;
	}
	__range_valid(false);
	return 0; //should newer be here!.. but sometimes we are ?
}

KviConsole * KviFrame::firstNotConnectedConsole()
{
	for(KviWindow * wnd = m_pWinList->first();wnd;wnd = m_pWinList->next())
	{
		if(wnd->type() == KVI_WINDOW_TYPE_CONSOLE)
		{
			if(!((KviConsole *)wnd)->connectionInProgress())
				return (KviConsole *)wnd;
		}
	}
	return 0;
}

void KviFrame::childWindowCloseRequest(KviWindow *wnd)
{
	closeWindow(wnd);
}

void KviFrame::unhighlightWindowsOfContext(KviIrcContext * c)
{
	for(KviWindow *w = m_pWinList->first();w;w = m_pWinList->next())
		if(w->context() == c)w->unhighlight();
}

void KviFrame::setActiveWindow(KviWindow *wnd)
{
	// ASSERT(m_pWinList->findRef(wnd))
	if(wnd->isMinimized())wnd->restore();
	if(wnd->mdiParent())wnd->setFocus();
	else wnd->delayedAutoRaise();
}

KviIrcConnection * KviFrame::activeConnection()
{
	return m_pActiveContext ? m_pActiveContext->connection() : 0;
}

void KviFrame::childWindowSelectionStateChange(KviWindow * pWnd,bool bGotSelectionNow)
{
	if(pWnd != g_pActiveWindow)return;
	emit activeWindowSelectionStateChanged(bGotSelectionNow);

}

void KviFrame::childContextStateChange(KviIrcContext * c)
{
	if(c != m_pActiveContext)return;
	emit activeContextStateChanged();
}

void KviFrame::childConnectionLagChange(KviIrcConnection * c)
{
	KviIrcContext * ctx = c->context();
	if(ctx != m_pActiveContext)return;
	emit activeConnectionLagChanged();
}

void KviFrame::childConnectionServerInfoChange(KviIrcConnection * c)
{
	KviIrcContext * ctx = c->context();
	if(ctx != m_pActiveContext)return;
	emit activeConnectionServerInfoChanged();
}

void KviFrame::childConnectionNickNameChange(KviIrcConnection * c)
{
	KviIrcContext * ctx = c->context();
	if(ctx != m_pActiveContext)return;
	emit activeConnectionNickNameChanged();
}

void KviFrame::childConnectionAwayStateChange(KviIrcConnection * c)
{
	KviIrcContext * ctx = c->context();
	if(ctx != m_pActiveContext)return;
	emit activeConnectionAwayStateChanged();
}

void KviFrame::childConnectionUserModeChange(KviIrcConnection * c)
{
	KviIrcContext * ctx = c->context();
	if(ctx != m_pActiveContext)return;
	emit activeConnectionUserModeChanged();
}


void KviFrame::childWindowActivated(KviWindow *wnd)
{
	// ASSERT(m_pWinList->findRef(wnd))
	if(g_pActiveWindow == wnd)return;
	if(g_pActiveWindow)g_pActiveWindow->lostUserFocus();
	// YES: it's HERE!
	g_pActiveWindow = wnd;

	bool bActiveContextChanged = (m_pActiveContext != wnd->context());
	m_pActiveContext = wnd->context();

	if(wnd->isMaximized() && wnd->mdiParent())updateCaption();
	m_pTaskBar->setActiveItem(wnd->taskBarItem());

	//wnd->gainedActiveWindowStatus(); // <-- atm unused

	if(g_pActiveWindow->view())
		g_pActiveWindow->view()->clearUnreaded();

	emit activeWindowChanged();
	if(bActiveContextChanged)emit activeContextChanged();

	KVS_TRIGGER_EVENT_0(KviEvent_OnWindowActivated,wnd);
}

void KviFrame::windowActivationChange(bool bOldActive)
{
	// if we have just been activated by the WM
	// then update the active window task bar item
	// It will then reset its highlight state
	// and hopefully make the dock widget work correctly
	// in this case.
	// This will also trigger the OnWindowActivated event :)
	if(isActiveWindow())
	{
		if(!bOldActive)
		{
			if(g_pActiveWindow)
			{
				KviWindow * pTmp = g_pActiveWindow;
				g_pActiveWindow = 0; // really ugly hack!
				childWindowActivated(pTmp);
			}
		}
	} else {
		if(g_pActiveWindow)g_pActiveWindow->lostUserFocus();
	}
}

void KviFrame::enteredSdiMode()
{
	updateCaption();
}

void KviFrame::leftSdiMode()
{
	updateCaption();
}

#define KVI_DEFAULT_FRAME_CAPTION "KVIrc " KVI_VERSION " " KVI_RELEASE_NAME

void KviFrame::updateCaption()
{
	if(g_pActiveWindow)
	{
		if(g_pActiveWindow->isMaximized() && g_pActiveWindow->mdiParent())
		{
			TQString tmp = g_pActiveWindow->plainTextCaption();
			tmp += TQChar(' ');
			tmp += KVI_DEFAULT_FRAME_CAPTION;
			setCaption(tmp);
			return;
		}
	}
	setCaption(KVI_DEFAULT_FRAME_CAPTION);
}


void KviFrame::closeEvent(TQCloseEvent *e)
{

	if(KVI_OPTION_BOOL(KviOption_boolCloseInTray))
	{
		e->ignore();

		if(!dockExtension())
		{
		    executeInternalCommand(KVI_INTERNALCOMMAND_DOCKWIDGET_SHOW);
		}
		if(dockExtension())
		{

			dockExtension()->setPrevWindowState(windowState());
			TQTimer::singleShot( 0, this, TQ_SLOT(hide()) );
		}
		return;
	}

	if(KVI_OPTION_BOOL(KviOption_boolConfirmCloseWhenThereAreConnections))
	{
		// check for running connections

		bool bGotRunningConnection = false;
		for(KviWindow * w = m_pWinList->first();w;w = m_pWinList->next())
		{
			if(w->type() == KVI_WINDOW_TYPE_CONSOLE)
			{
				if(((KviConsole *)w)->connectionInProgress())
				{
					bGotRunningConnection = true;
					break;
				}
			}
		}

		if(bGotRunningConnection)
		{
			TQString txt = "<p>";
			txt += __tr2qs("There are active connections, are you sure you wish to ");
			txt += __tr2qs("quit KVIrc?");
			txt += "</p>";

			switch(TQMessageBox::warning(this,__tr2qs("Confirmation - KVIrc"),txt,__tr2qs("&Yes"),__tr2qs("&Always"),__tr2qs("&No"),2,2))
			{
				case 0:
					// ok to close
				break;
				case 1:
					// ok to close but don't ask again
					KVI_OPTION_BOOL(KviOption_boolConfirmCloseWhenThereAreConnections) = false;
				break;
				case 2:
					e->ignore();
					return;
				break;
			}
		}
	}

	e->accept();

	if(g_pApp)
		g_pApp->destroyFrame();
}

void KviFrame::resizeEvent(TQResizeEvent *e)
{
	KVI_OPTION_RECT(KviOption_rectFrameGeometry) = TQRect(pos().x(),pos().y(),
			size().width(),size().height());
	KviTalMainWindow::resizeEvent(e);
}

void KviFrame::updatePseudoTransparency()
{
#ifdef COMPILE_PSEUDO_TRANSPARENCY
	if(g_pShadedParentGlobalDesktopBackground)m_pMdi->viewport()->update();

	if(g_pShadedChildGlobalDesktopBackground)
	{
		for(KviWindow * wnd = m_pWinList->first();wnd;wnd = m_pWinList->next())wnd->updateBackgrounds();
		m_pTaskBar->updatePseudoTransparency();
	}
#endif
}

void KviFrame::moveEvent(TQMoveEvent *e)
{
	KVI_OPTION_RECT(KviOption_rectFrameGeometry) = TQRect(pos().x(),pos().y(),
			size().width(),size().height());
#ifdef COMPILE_PSEUDO_TRANSPARENCY
	updatePseudoTransparency();
#endif
	KviTalMainWindow::moveEvent(e);
}

void KviFrame::applyOptions()
{
	m_pMdi->update();
	for(KviWindow * wnd = m_pWinList->first();wnd;wnd = m_pWinList->next())wnd->applyOptions();
	updateCaption();

	m_pTaskBar->applyOptions();
}

void KviFrame::toggleStatusBar()
{
	if(m_pStatusBar)
	{
		delete m_pStatusBar;
		m_pStatusBar = 0;
	} else {
		//if(statusBar())delete statusBar(); // kill any existing status bar (TQt BUG)

		m_pStatusBar = new KviStatusBar(this);
		m_pStatusBar->load();
		m_pStatusBar->show();
		setUpLayout();
	}
}

void KviFrame::fillToolBarsPopup(KviTalPopupMenu * p)
{
	p->clear();

	disconnect(p,TQ_SIGNAL(activated(int)),this,TQ_SLOT(toolbarsPopupSelected(int))); // just to be sure
	connect(p,TQ_SIGNAL(activated(int)),this,TQ_SLOT(toolbarsPopupSelected(int)));

	int id;
	int cnt = 0;

	KviModuleExtensionDescriptorList * l = g_pModuleExtensionManager->getExtensionList("toolbar");
	if(l)
	{
		for(KviModuleExtensionDescriptor * d = l->first();d;d = l->next())
		{
			TQString label = __tr2qs("Show %1").arg(d->visibleName());
			if(d->icon())id = p->insertItem(*(d->icon()),label);
			else id = p->insertItem(label);
			p->setItemChecked(id,moduleExtensionToolBar(d->id()));
			p->setItemParameter(id,d->id());
			cnt++;
		}
	}

	// FIXME: Should this display "Hide %1" when the toolbar is already visible ?
	KviPointerHashTableIterator<TQString,KviCustomToolBarDescriptor> it2(*(KviCustomToolBarManager::instance()->descriptors()));
	if(it2.current())
	{
		if(cnt > 0)p->insertSeparator();
		while(KviCustomToolBarDescriptor * d = it2.current())
		{
			TQString label = __tr2qs("Show %1").arg(d->label());
			TQString ico = d->iconId();
			// use the icon only if there is no check
			if(d->toolBar())
			{
				id = p->insertItem(label);
				p->setItemChecked(id,true);
			} else {
				if(!ico.isEmpty())
				{
					TQPixmap * pix = g_pIconManager->getImage(d->iconId());
					if(pix)
					{
						id = p->insertItem(*pix,label);
					} else {
						id = p->insertItem(label);
					}
				} else {
					id = p->insertItem(label);
				}
			}
			p->setItemParameter(id,d->internalId());
			++it2;
			cnt++;
		}
	}

	if(cnt > 0)p->insertSeparator();
	p->insertItem(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_TOOLBAR)),__tr2qs("Customize..."),this,TQ_SLOT(customizeToolBars()));
}

void KviFrame::customizeToolBars()
{
	KviKvsScript::run("toolbareditor.open",g_pActiveWindow);
}

void KviFrame::toolbarsPopupSelected(int id)
{
	const TQObject * o = sender();
	if(!o)return;
	if(!o->inherits("KviTalPopupMenu"))return;
	const KviTalPopupMenu * p = (const KviTalPopupMenu *)o;
	int idext = p->itemParameter(id);

	KviCustomToolBarDescriptor * dd = KviCustomToolBarManager::instance()->findDescriptorByInternalId(idext);
	if(dd)
	{
		if(dd->toolBar())delete dd->toolBar();
		else dd->createToolBar();
	}

	if(KviMexToolBar * t = moduleExtensionToolBar(idext))
	{
		t->die();
	} else {
		g_pModuleExtensionManager->allocateExtension("toolbar",idext,firstConsole());
	}
}



bool KviFrame::focusNextPrevChild(bool next)
{
	//tqDebug("FOCUS NEXT PREV CHILD");
	TQWidget * w = focusWidget();
	if(w)
	{
		if(w->focusPolicy() == TQWidget::StrongFocus)return false;
		//TQVariant v = w->property("KviProperty_FocusOwner");
		//if(v.isValid())return false; // Do NOT change the focus widget!

		if(w->parent())
		{
			TQVariant v = w->parent()->property("KviProperty_ChildFocusOwner");
			if(v.isValid())return false; // Do NOT change the focus widget!
		}
	}
	// try to focus the widget on top of the Mdi
	if(m_pMdi->topChild())
	{
		m_pMdi->focusTopChild();
		return false;
	}
	return KviTalMainWindow::focusNextPrevChild(next);
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// Toolbar positioning stuff
////////////////////////////////////////////////////////////////////////////////////////////////////


void KviFrame::saveToolBarPositions()
{
	TQString szTemp;
	g_pApp->getLocalKvircDirectory(szTemp,KviApp::Config,KVI_CONFIGFILE_TOOLBARS);

	TQFile f(szTemp);
	if(f.open(IO_WriteOnly | IO_Truncate))
	{
		TQTextStream ts(&f);
		ts << *this;
		f.close();
	}
}

void KviFrame::restoreToolBarPositions()
{
	TQString szTemp;
	g_pApp->getLocalKvircDirectory(szTemp,KviApp::Config,KVI_CONFIGFILE_TOOLBARS);

	TQFile f(szTemp);

	bool bNeedDefaults = false;

	if(f.open(IO_ReadOnly))
	{
		TQTextStream ts(&f);
		ts >> *this;
		f.close();
	} else {
		bNeedDefaults = true;
	}

	if(m_pTaskBar->inherits("KviTreeTaskBar"))
	{
		TQDockArea * a = m_pTaskBar->area();
		if((a == topDock()) || (a == bottomDock()))
		{
			// nope.... need to move it
			a->removeDockWindow(m_pTaskBar,true,false);

			//int iMaxWidth = m_pTaskBar->maximumWidth();
			leftDock()->moveDockWindow(m_pTaskBar);
			//m_pTaskBar->setMaximumWidth(iMaxWidth);
			//m_pTaskBar->setOrientationVertical);
		}
		// ensure that it is not too wide
		if(m_pTaskBar->width() > 600)
			m_pTaskBar->setFixedExtentWidth(250);
	} /*else if(m_pTaskBar->inherits("KviClassicTaskBar"))
	{
		TQDockArea * a = m_pTaskBar->area();
		if((a == leftDock()) || (a == rightDock()))
		{
			// nope.... need to move it
			a->removeDockWindow(m_pTaskBar,true,false);
			bottomDock()->moveDockWindow(m_pTaskBar);
			bottomDock()->lineUp(true);
		}
	}*/

	if(bNeedDefaults)
		lineUpDockWindows(false);
}


void KviFrame::createTaskBar()
{
	if(KVI_OPTION_BOOL(KviOption_boolUseTreeWindowListTaskBar))
	{
		m_pTaskBar = new KviTreeTaskBar();
		setDockEnabled(m_pTaskBar,TQt::DockTop,false);
		setDockEnabled(m_pTaskBar,TQt::DockBottom,false);
	} else {
		m_pTaskBar = new KviClassicTaskBar();
		setDockEnabled(m_pTaskBar,TQt::DockTop,true);
		setDockEnabled(m_pTaskBar,TQt::DockBottom,true);
	}
	setDockEnabled(m_pTaskBar,TQt::DockLeft,true);
	setDockEnabled(m_pTaskBar,TQt::DockRight,true);
}

void KviFrame::recreateTaskBar()
{
	TQString szOldClass = m_pTaskBar->className();

	saveToolBarPositions();
	KviWindow * w;
	for(w = m_pWinList->first();w;w = m_pWinList->next())
	{
		w->destroyTaskBarItem();
	}
	removeDockWindow(m_pTaskBar);
	delete m_pTaskBar;
	createTaskBar();
	for(w = m_pWinList->first();w;w = m_pWinList->next())
	{
		w->createTaskBarItem();
	}
	restoreToolBarPositions();


	/*
	TQString szNewClass = m_pTaskBar->className();
	if(szOldClass != szNewClass)
	{
		// the class changed...
		// make sure that the tree task bar is in the left or right dock
		// and the classic one is in the top or bottom on

		TQt::Dock dock;
		int index;
		bool nl;
		int eo;
		getLocation(m_pTaskBar,dock,index,nl,eo);

		if(KVI_OPTION_BOOL(KviOption_boolUseTreeWindowListTaskBar))
		{
			if((dock == TQt::Bottom) || (dock == TQt::Top))
				moveDockWindow(m_pTaskBar,TQt::Left);
		} else {
			if((dock == TQt::Left) || (dock == TQt::Right))
				moveDockWindow(m_pTaskBar,TQt::Bottom);
		}
	}
	*/

	if(g_pActiveWindow)m_pTaskBar->setActiveItem(g_pActiveWindow->taskBarItem());
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// Some accelerators
////////////////////////////////////////////////////////////////////////////////////////////////////

void KviFrame::maximizeWindow(void)
{
	if(!g_pActiveWindow)return;
	if(g_pActiveWindow->isMaximized())g_pActiveWindow->restore();
	else g_pActiveWindow->maximize();
}

void KviFrame::minimizeWindow(void)
{
	if(g_pActiveWindow)g_pActiveWindow->minimize();
}

void KviFrame::switchToPrevWindow(void)
{
	m_pTaskBar->switchWindow(false,false);
}

void KviFrame::switchToNextWindow(void)
{
	m_pTaskBar->switchWindow(true,false);
}

void KviFrame::switchToPrevWindowInContext(void)
{
	m_pTaskBar->switchWindow(false,true);
}

void KviFrame::switchToNextWindowInContext(void)
{
	m_pTaskBar->switchWindow(true,true);
}

void KviFrame::hideEvent ( TQHideEvent * e)
{
	if(KVI_OPTION_BOOL(KviOption_boolMinimizeInTray))
	{
		if(e->spontaneous())
		{

		if(!dockExtension())
		{
			executeInternalCommand(KVI_INTERNALCOMMAND_DOCKWIDGET_SHOW);
		}
			 TQTimer::singleShot( 0, this, TQ_SLOT(hide()) );
		}

	}
}

#include "kvi_frame.moc"
