/*********
*
* This file is part of BibleTime's source code, http://www.bibletime.info/.
*
* Copyright 1999-2006 by the BibleTime developers.
* The BibleTime source code is licensed under the GNU General Public License version 2.0.
*
**********/



#include "cmdiarea.h"
#include "backend/cswordmoduleinfo.h"
#include "backend/cswordversekey.h"

#include "frontend/displaywindow/cdisplaywindow.h"
#include "frontend/keychooser/ckeychooser.h"

#include "config.h"

//KDE includes
#include <tdepopupmenu.h>
#include <tdeapplication.h>
#include <tdelocale.h>

//QT includes
#include <tqobjectlist.h>
#include <tqtimer.h>
#include <tqevent.h>
#include <tqtimer.h>


CMDIArea::CMDIArea(TQWidget *parent, const char *name )
: TQWorkspace(parent, name),
m_guiOption(Nothing),
m_childEvent(false),
m_appCaption(TQString()) {
	initView();
	initConnections();
	readSettings();
}


/** Initializes the view of the MDI area */
void CMDIArea::initView() {
	setPaletteBackgroundColor( parentWidget()->paletteBackgroundColor() ); //work around a KDE bug (IMHO was in KDE 2.x)
}

/** Initilizes the connectiosn to SIGNALS */
void CMDIArea::initConnections() {
	connect(this, TQT_SIGNAL(windowActivated(TQWidget*)),
			this, TQT_SLOT(slotClientActivated(TQWidget*)));
}

/** Called whan a client window was activated */
void CMDIArea::slotClientActivated(TQWidget* client) {
	if (!client || !isUpdatesEnabled()) {
		return;
	}

	CDisplayWindow* sp = dynamic_cast<CDisplayWindow*>(client);
	Q_ASSERT(sp);
	if (!sp || !sp->isReady()) {
		return;
	}

	TQWidgetList windows = windowList();
	for ( TQWidget* w = windows.first(); w; w = windows.next() ) {
		//Don't use!! It would disable accel enabling for the active window, see CDisplayWindow::windowActivated
		/*    if (w == client)
		    continue;
		*/

		CDisplayWindow* window = dynamic_cast<CDisplayWindow*>(w);
		window->windowActivated( (window == sp) ? true : false);
	}

	emit sigSetToplevelCaption( ( m_appCaption = client->caption().stripWhiteSpace() ) );
}

/** Reimplementation. Used to make use of the fixedGUIOption part. */
void CMDIArea::childEvent( TQChildEvent * e ) {
	TQWorkspace::childEvent(e);

	if ( m_childEvent || !e) {
		return;
	}

	m_childEvent = true;

	if (!windowList().count()) {
		m_appCaption = TQString();
		emit sigSetToplevelCaption( TDEApplication::kApplication()->makeStdCaption(m_appCaption) );
		emit sigLastPresenterClosed();
	}

	if ((e->inserted() || e->removed()) ) {
		if (e->inserted() && e->child() && e->child()->inherits("CDisplayWindow")) {
			e->child()->installEventFilter(this); //make sure we catch the events of the new window
		}
		else if (e->removed() && e->child() && e->child()->inherits("CDisplayWindow")) {
			e->child()->removeEventFilter(this); //make sure we catch the events of the new window
		}

		triggerWindowUpdate();
	}

	m_childEvent = false;
}

/** Reimplementation */
void CMDIArea::resizeEvent(TQResizeEvent* e) {
	TQWorkspace::resizeEvent(e);

	if (isUpdatesEnabled()) {
		triggerWindowUpdate();
	};
}

/**  */
void CMDIArea::saveSettings() {}

/**  */
void CMDIArea::readSettings() {}

/** Deletes all the presenters in the MDI area. */
void CMDIArea::deleteAll() {
	closeAllWindows();
}

/** Enable / disable autoCascading */
void CMDIArea::setGUIOption( const MDIOption& newOption ) {
	//now do the initial action
	m_guiOption = newOption;

	triggerWindowUpdate();
}

/**  */
void CMDIArea::myTileVertical() {
	if (!isUpdatesEnabled() || !usableWindowList().count() ) {
		return;
	}

	TQPtrList<TQWidget> windows = usableWindowList();

	if ((windows.count() == 1) && windows.at(0)) {
		m_appCaption = windows.at(0)->caption();
		windows.at(0)->showMaximized();
	}
	else {
		TQWidget* active = activeWindow();
		TQWorkspace::tile();
		active->setFocus();
	}
}

void CMDIArea::myTileHorizontal() {
	if (!isUpdatesEnabled() || !usableWindowList().count() ) {
		return;
	}

	TQPtrList<TQWidget> windows = usableWindowList();

	if ((windows.count() == 1) && windows.at(0)) {
		m_appCaption = windows.at(0)->caption();
		windows.at(0)/*->parentWidget()*/->showMaximized();
	}
	else {

		TQWidget* active = activeWindow();
		if (active->isMaximized()) {
			active->showNormal();
		}

		blockSignals(true);
		setUpdatesEnabled(false);
		int heightForEach = height() / windows.count();
		int y = 0;
		for ( int i = 0; i < int(windows.count()); ++i ) {
			TQWidget *window = windows.at(i);
			window->parentWidget()->showNormal();
			tqApp->sendPostedEvents( 0, TQEvent::ShowNormal );

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

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

		setUpdatesEnabled(true);
		active->setFocus();
		blockSignals(false);
	}

}

/**  */
void CMDIArea::myCascade() {
	if (!isUpdatesEnabled() || !usableWindowList().count() ) {
		return;
	}

	TQPtrList<TQWidget> windows = usableWindowList();
	if ( !windows.count() ) {
		return;
	}

	if ((windows.count() == 1) && windows.at(0)) {
		m_appCaption = windows.at(0)->caption();
		windows.at(0)->parentWidget()->showMaximized();
	}
	else {
		const int offsetX = 40;
		const int offsetY = 40;
		const int windowWidth =  width() - (windows.count()-1)*offsetX;
		const int windowHeight = height() - (windows.count()-1)*offsetY;

		int x = 0;
		int y = 0;

		TQWidget* const active = activeWindow();
		if (active->isMaximized()) {
			active->showNormal();
		}

		blockSignals(true);
		setUpdatesEnabled(false);

		for (int i(0); i < int(windows.count()); ++i) {
			TQWidget* window = windows.at(i);
			if (window == active) { //leave out the active window which should be the top window
				continue;
			}

			window->setUpdatesEnabled(false);

			window->parentWidget()->raise(); //make it the on-top-of-window-stack window to make sure they're in the right order
			window->parentWidget()->setGeometry(x, y, windowWidth, windowHeight);
			x += offsetX;
			y += offsetY;

			window->setUpdatesEnabled(true);
		}

		setUpdatesEnabled(true);

		active->parentWidget()->setGeometry(x, y, windowWidth, windowHeight);
		active->parentWidget()->raise();
		active->setActiveWindow();

		blockSignals(false);
	}
}

/*!
    \fn CMDIArea::emitWindowCaptionChanged()
 */
void CMDIArea::emitWindowCaptionChanged() {
	if (activeWindow()) {
		m_appCaption = activeWindow()->caption();
	}

	emit sigSetToplevelCaption(currentApplicationCaption());
}


/*!
    \fn CMDIArea::usableWindowsCount()
 */
TQPtrList<TQWidget> CMDIArea::usableWindowList() {
	TQPtrList<TQWidget> ret;

	TQWidgetList windows = windowList();
	for ( TQWidget* w = windows.first(); w; w = windows.next() ) {
		if (w->isMinimized() || w->isHidden()) { //not usable for us
			continue;
		}

		ret.append( w );
	}

	return ret;
}

bool CMDIArea::eventFilter( TQObject *o, TQEvent *e ) {
	Q_ASSERT(o);
	Q_ASSERT(e);

	TQWidget* w = dynamic_cast<TQWidget*>( o );
	bool ret = TQWorkspace::eventFilter(o,e);

 	if ( w && (e->type() == TQEvent::WindowStateChange) ) {
 		if (o->inherits("CDisplayWindow") && ((w->windowState() & TQt::WindowMinimized) || w->isHidden())) { //window was minimized, trigger a tile/cascade update if necessary
			triggerWindowUpdate();
			ret = false;
		}
		else if (!o->inherits("CDisplayWindow")){
			tqDebug("CMDIArea: bad mdi child classname: %s", o->className());
			//o->dumpObjectInfo();
			//o->dumpObjectTree();
		}
	}
	return ret; // standard event processing
}


/*!
    \fn CMDIArea::triggerWindowUpdate()
 */
void CMDIArea::triggerWindowUpdate() {
	tqDebug("CMDIArea::triggerWindowUpfdate");

	if (isUpdatesEnabled() && usableWindowList().count() ) {
		switch (m_guiOption) {
			case autoTileVertical:
			TQTimer::singleShot(0, this, TQT_SLOT(myTileVertical()));
			break;
			case autoTileHorizontal:
			TQTimer::singleShot(0, this, TQT_SLOT(myTileHorizontal()));
			break;
			case autoCascade:
			TQTimer::singleShot(0, this, TQT_SLOT(myCascade()));
			break;
			default:
			tqDebug("CMDIArea::triggerWindowUpdate: no known m_guiType");
			break;
		}
	}
}

#include "cmdiarea.moc"
