/* This file is part of the KDE project
   Copyright (C) 2004 Cedric Pasteur <cedric.pasteur@free.fr>
   Copyright (C) 2005 Jaroslaw Staniek <js@iidea.pl>

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License as published by the Free Software Foundation; either
   version 2 of the License, or (at your option) any later version.

   This library 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
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this library; see the file COPYING.LIB.  If not, write to
   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
*/
#include <tqdom.h>
#include <tqwidget.h>
#include <tqlayout.h>
#include <tqlabel.h>
#include <tqsplitter.h>
#include <tqmetaobject.h>

#include <kdebug.h>
#include <tdelocale.h>
#include <tdepopupmenu.h>
#include <tdemessagebox.h>
#include <tdeaccelmanager.h>

#include "formIO.h"
#include "container.h"
#include "objecttree.h"
#include "formmanager.h"
#include "form.h"
#include "widgetlibrary.h"
#include "events.h"
#include "utils.h"
#include "widgetpropertyset.h"
#include "widgetwithsubpropertiesinterface.h"
#include <koproperty/property.h>

#include "commands.h"

using namespace KFormDesigner;

// Command

Command::Command()
 : KCommand()
{
}

Command::~Command()
{
}

// PropertyCommand

PropertyCommand::PropertyCommand(WidgetPropertySet *set, const TQCString &wname,
	const TQVariant &oldValue, const TQVariant &value, const TQCString &property)
  : Command(), m_propSet(set), m_value(value), m_property(property)
{
	m_oldvalues.insert(wname, oldValue);
}

PropertyCommand::PropertyCommand(WidgetPropertySet *set, const TQMap<TQCString, TQVariant> &oldvalues,
	const TQVariant &value, const TQCString &property)
  : Command(), m_propSet(set), m_value(value), m_oldvalues(oldvalues), m_property(property)
{
}

/*
MultiCommand::MultiCommand()
{
}

MultiCommandGroup::addSubCommand(PropertyCommand* subCommand)
  : Command(), m_propSet(set), m_value(value), m_oldvalues(oldvalues), m_property(property)
{
}
*/

void
PropertyCommand::setValue(const TQVariant &value)
{
	m_value = value;
	emit FormManager::self()->dirty(FormManager::self()->activeForm());
}

void
PropertyCommand::execute()
{
	FormManager::self()->activeForm()->selectFormWidget();
	m_propSet->setUndoing(true);

	TQMap<TQCString, TQVariant>::ConstIterator endIt = m_oldvalues.constEnd();
	for(TQMap<TQCString, TQVariant>::ConstIterator it = m_oldvalues.constBegin(); it != endIt; ++it)
	{
		ObjectTreeItem* item = FormManager::self()->activeForm()->objectTree()->lookup(it.key());
		if (item) {//we're checking for item!=0 because the name could be of a form widget
			FormManager::self()->activeForm()->setSelectedWidget(item->widget(), true);
		}
	}

	(*m_propSet)[m_property] = m_value;
	m_propSet->setUndoing(false);
}

void
PropertyCommand::unexecute()
{
	FormManager::self()->activeForm()->selectFormWidget();
	m_propSet->setUndoing(true);

	TQMap<TQCString, TQVariant>::ConstIterator endIt = m_oldvalues.constEnd();
	for(TQMap<TQCString, TQVariant>::ConstIterator it = m_oldvalues.constBegin(); it != endIt; ++it)
	{
		ObjectTreeItem* item = FormManager::self()->activeForm()->objectTree()->lookup(it.key());
		if (!item)
			continue; //better this than a crash
		TQWidget *widg = item->widget();
		FormManager::self()->activeForm()->setSelectedWidget(widg, true);
		//m_propSet->setSelectedWidget(widg, true);

		WidgetWithSubpropertiesInterface* subpropIface = dynamic_cast<WidgetWithSubpropertiesInterface*>(widg);
		TQWidget *subWidget = (subpropIface && subpropIface->subwidget()) ? subpropIface->subwidget() : widg;
		if (-1!=subWidget->metaObject()->findProperty( m_property, true ))
			subWidget->setProperty(m_property, it.data());
	}

	(*m_propSet)[m_property] = m_oldvalues.begin().data();
	m_propSet->setUndoing(false);
}

TQString
PropertyCommand::name() const
{
	if(m_oldvalues.count() >= 2)
		return i18n("Change \"%1\" property for multiple widgets" ).arg(TQString(m_property));
	else
		return i18n("Change \"%1\" property for widget \"%2\"" ).arg(TQString(m_property)).arg(TQString(m_oldvalues.begin().key()));
}

void
PropertyCommand::debug()
{
	kdDebug() << "PropertyCommand: name=\"" << name() << "\" widgets=" << m_oldvalues.keys()
		<< " value=" << m_value << " oldValues=" << m_oldvalues.values() << endl;
}

// GeometryPropertyCommand (for multiples widgets)

GeometryPropertyCommand::GeometryPropertyCommand(WidgetPropertySet *set,
	const TQStringList &names, const TQPoint& oldPos)
 : Command(), m_propSet(set), m_names(names), m_oldPos(oldPos)
{
}

void
GeometryPropertyCommand::execute()
{
	m_propSet->setUndoing(true);
	int dx = m_pos.x() - m_oldPos.x();
	int dy = m_pos.y() - m_oldPos.y();

	TQStringList::ConstIterator endIt = m_names.constEnd();
	// We move every widget in our list by (dx, dy)
	for(TQStringList::ConstIterator it = m_names.constBegin(); it != endIt; ++it)
	{
		ObjectTreeItem* item = FormManager::self()->activeForm()->objectTree()->lookup(*it);
		if (!item)
			continue; //better this than a crash
		TQWidget *w = item->widget();
		w->move(w->x() + dx, w->y() + dy);
	}
	m_propSet->setUndoing(false);
}

void
GeometryPropertyCommand::unexecute()
{
	m_propSet->setUndoing(true);
	int dx = m_pos.x() - m_oldPos.x();
	int dy = m_pos.y() - m_oldPos.y();

	TQStringList::ConstIterator endIt = m_names.constEnd();
	// We move every widget in our list by (-dx, -dy) to undo the move
	for(TQStringList::ConstIterator it = m_names.constBegin(); it != endIt; ++it)
	{
		ObjectTreeItem* item = FormManager::self()->activeForm()->objectTree()->lookup(*it);
		if (!item)
			continue; //better this than a crash
		TQWidget *w = item->widget();
		w->move(w->x() - dx, w->y() - dy);
	}
	m_propSet->setUndoing(false);
}

void
GeometryPropertyCommand::setPos(const TQPoint& pos)
{
	m_pos = pos;
	emit FormManager::self()->dirty(FormManager::self()->activeForm());
}

TQString
GeometryPropertyCommand::name() const
{
	return i18n("Move multiple widgets");
}

void
GeometryPropertyCommand::debug()
{
	kdDebug() << "GeometryPropertyCommand: pos=" << m_pos << " oldPos=" << m_oldPos
		<< " widgets=" << m_names << endl;
}

/////////////////  AlignWidgetsCommand  ////////

AlignWidgetsCommand::AlignWidgetsCommand(int type, WidgetList &list, Form *form)
: Command(), m_form(form), m_type(type)
{
	for(TQWidget *w = list.first(); w; w = list.next())
		m_pos.insert(w->name(), w->pos());
}

void
AlignWidgetsCommand::execute()
{
	// To avoid creation of GeometryPropertyCommand
	m_form->selectFormWidget();

	int gridX = m_form->gridSize();
	int gridY = m_form->gridSize();
	TQWidget *parentWidget = m_form->selectedWidgets()->first()->parentWidget();
	int tmpx, tmpy;

	WidgetList list;
	TQMap<TQCString, TQPoint>::ConstIterator endIt = m_pos.constEnd();
	for(TQMap<TQCString, TQPoint>::ConstIterator it = m_pos.constBegin(); it != endIt; ++it)
	{
		ObjectTreeItem *item = m_form->objectTree()->lookup(it.key());
		if(item && item->widget())
			list.append(item->widget());
	}

	switch(m_type)
	{
		case AlignToGrid:
		{
			for(TQWidget *w = list.first(); w; w = list.next())
			{
				tmpx = int( (float)w->x() / ((float)gridX) + 0.5 ) * gridX;
				tmpy = int( (float)w->y() / ((float)gridY) + 0.5 ) * gridY;

				if((tmpx != w->x()) || (tmpy != w->y()))
					w->move(tmpx, tmpy);
			}
			break;
		}

		case AlignToLeft:
		{
			tmpx = parentWidget->width();
			for(TQWidget *w = list.first(); w; w = list.next())
			{
				if(w->x() < tmpx)
					tmpx = w->x();
			}

			for(TQWidget *w = list.first(); w; w = list.next())
				w->move(tmpx, w->y());
			break;
		}

		case AlignToRight:
		{
			tmpx = 0;
			for(TQWidget *w = list.first(); w; w = list.next())
			{
				if(w->x() + w->width() > tmpx)
					tmpx = w->x() + w->width();
			}

			for(TQWidget *w = list.first(); w; w = list.next())
				w->move(tmpx - w->width(), w->y());
			break;
		}

		case AlignToTop:
		{
			tmpy = parentWidget->height();
			for(TQWidget *w = list.first(); w; w = list.next())
			{
				if(w->y() < tmpy)
					tmpy = w->y();
			}

			for(TQWidget *w = list.first(); w; w = list.next())
				w->move(w->x(), tmpy);
			break;
		}

		case AlignToBottom:
		{
			tmpy = 0;
			for(TQWidget *w = list.first(); w; w = list.next())
			{
				if(w->y() + w->height() > tmpy)
					tmpy = w->y() + w->height();
			}

			for(TQWidget *w = list.first(); w; w = list.next())
				w->move(w->x(), tmpy - w->height());
			break;
		}

		default:
			return;
	}

	// We restore selection
	for(TQWidget *w = list.first(); w; w = list.next())
		m_form->setSelectedWidget(w, true);
}

void
AlignWidgetsCommand::unexecute()
{
	// To avoid creation of GeometryPropertyCommand
	m_form->selectFormWidget();
	// We move widgets to their original pos
	TQMap<TQCString, TQPoint>::ConstIterator endIt = m_pos.constEnd();
	for(TQMap<TQCString, TQPoint>::ConstIterator it = m_pos.constBegin(); it != endIt; ++it)
	{
		ObjectTreeItem *item = m_form->objectTree()->lookup(it.key());
		if(item && item->widget())
			item->widget()->move( m_pos[item->widget()->name()] );
		m_form->setSelectedWidget(item->widget(), true); // We restore selection
	}
}

TQString
AlignWidgetsCommand::name() const
{
	switch(m_type)
	{
		case AlignToGrid:
			return i18n("Align Widgets to Grid");
		case AlignToLeft:
			return i18n("Align Widgets to Left");
		case AlignToRight:
			return i18n("Align Widgets to Right");
		case AlignToTop:
			return i18n("Align Widgets to Top");
		case AlignToBottom:
			return i18n("Align Widgets to Bottom");
		default:
			return TQString();
	}
}

void
AlignWidgetsCommand::debug()
{
	kdDebug() << "AlignWidgetsCommand: name=\"" << name() << "\" form=" << m_form->widget()->name()
		<< " widgets=" << m_pos.keys() << endl;
}

///// AdjustSizeCommand ///////////

AdjustSizeCommand::AdjustSizeCommand(int type, WidgetList &list, Form *form)
: Command(), m_form(form), m_type(type)
{
	for(TQWidget *w = list.first(); w; w = list.next())
	{
		if(w->parentWidget() && w->parentWidget()->isA("TQWidgetStack"))
		{
			w = w->parentWidget(); // widget is WidgetStack page
			if(w->parentWidget() && w->parentWidget()->inherits("TQTabWidget")) // widget is tabwidget page
				w = w->parentWidget();
		}

		m_sizes.insert(w->name(), w->size());
		if(m_type == SizeToGrid) // SizeToGrid also move widgets
			m_pos.insert(w->name(), w->pos());
	}
}

void
AdjustSizeCommand::execute()
{
	// To avoid creation of GeometryPropertyCommand
	m_form->selectFormWidget();

	int gridX = m_form->gridSize();
	int gridY = m_form->gridSize();
	int tmpw=0, tmph=0;

	WidgetList list;
	TQMap<TQCString, TQSize>::ConstIterator endIt = m_sizes.constEnd();
	for(TQMap<TQCString, TQSize>::ConstIterator it = m_sizes.constBegin(); it != endIt; ++it)
	{
		ObjectTreeItem *item = m_form->objectTree()->lookup(it.key());
		if(item && item->widget())
			list.append(item->widget());
	}

	switch(m_type)
	{
		case SizeToGrid:
		{
			int tmpx=0, tmpy=0;
			// same as in 'Align to Grid' + for the size
			for(TQWidget *w = list.first(); w; w = list.next())
			{
				tmpx = int( (float)w->x() / ((float)gridX) + 0.5 ) * gridX;
				tmpy = int( (float)w->y() / ((float)gridY) + 0.5 ) * gridY;
				tmpw = int( (float)w->width() / ((float)gridX) + 0.5 ) * gridX;
				tmph = int( (float)w->height() / ((float)gridY) + 0.5 ) * gridY;

				if((tmpx != w->x()) || (tmpy != w->y()))
					w->move(tmpx, tmpy);
				if((tmpw != w->width()) || (tmph != w->height()))
					w->resize(tmpw, tmph);
			}
			break;
		}

		case SizeToFit:
		{
			for(TQWidget *w = list.first(); w; w = list.next()) {
				ObjectTreeItem *item = m_form->objectTree()->lookup(w->name());
				if(item && !item->children()->isEmpty()) { // container
					TQSize s;
					if(item->container() && item->container()->layout())
						s = w->sizeHint();
					else
						s = getSizeFromChildren(item);
					// minimum size for containers
					if(s.width()  <  30)
						s.setWidth(30);
					if(s.height() < 30)
						s.setHeight(30);
					// small hack for flow layouts
					int type = item->container() ? item->container()->layoutType() : Container::NoLayout;
					if(type == Container::HFlow)
						s.setWidth(s.width() + 5);
					else if(type == Container::VFlow)
						s.setHeight(s.height() + 5);
					w->resize(s);
				}
				else if(item && item->container()) // empty container
					w->resize(item->container()->form()->gridSize() * 5, item->container()->form()->gridSize() * 5); // basic size
				else {
					TQSize sizeHint(w->sizeHint());
					if (sizeHint.isValid())
						w->resize(sizeHint);
				}
			}
			break;
		}

		case SizeToSmallWidth:
		{
			for(TQWidget *w = list.first(); w; w = list.next())
			{
				if((tmpw == 0) || (w->width() < tmpw))
					tmpw = w->width();
			}

			for(TQWidget *w = list.first(); w; w = list.next())
			{
				if(tmpw != w->width())
					w->resize(tmpw, w->height());
			}
			break;
		}

		case SizeToBigWidth:
		{
			for(TQWidget *w = list.first(); w; w = list.next())
			{
				if(w->width() > tmpw)
					tmpw = w->width();
			}

			for(TQWidget *w = list.first(); w; w = list.next())
			{
				if(tmpw != w->width())
					w->resize(tmpw, w->height());
			}
			break;
		}

		case SizeToSmallHeight:
		{
			for(TQWidget *w = list.first(); w; w = list.next())
			{
				if((tmph == 0) || (w->height() < tmph))
					tmph = w->height();
			}

			for(TQWidget *w = list.first(); w; w = list.next())
			{
				if(tmph != w->height())
					w->resize(w->width(), tmph);
			}
			break;
		}

		case SizeToBigHeight:
		{
			for(TQWidget *w = list.first(); w; w = list.next())
			{
				if(w->height() > tmph)
					tmph = w->height();
			}

			for(TQWidget *w = list.first(); w; w = list.next())
			{
				if(tmph != w->height())
					w->resize(w->width(), tmph);
			}
			break;
		}

		default:
			break;
	}

	// We restore selection
	for(TQWidget *w = list.first(); w; w = list.next())
		m_form->setSelectedWidget(w, true);
}

TQSize
AdjustSizeCommand::getSizeFromChildren(ObjectTreeItem *item)
{
	if(!item->container()) // multi pages containers (eg tabwidget)
	{
		TQSize s;
		// get size for each container, and keep the biggest one
		for(ObjectTreeItem *tree = item->children()->first(); tree; tree = item->children()->next())
			s = s.expandedTo(getSizeFromChildren(tree));
		return s;
	}

	int tmpw = 0, tmph = 0;
	for(ObjectTreeItem *tree = item->children()->first(); tree; tree = item->children()->next()) {
		if(!tree->widget())
			continue;
		tmpw = TQMAX(tmpw, tree->widget()->geometry().right());
		tmph = TQMAX(tmph, tree->widget()->geometry().bottom());
	}

	return TQSize(tmpw, tmph) + TQSize(10, 10);
}

void
AdjustSizeCommand::unexecute()
{
	// To avoid creation of GeometryPropertyCommand
	m_form->selectFormWidget();
	// We resize widgets to their original size
	TQMap<TQCString, TQSize>::ConstIterator endIt = m_sizes.constEnd();
	for(TQMap<TQCString, TQSize>::ConstIterator it = m_sizes.constBegin(); it != endIt; ++it)
	{
		ObjectTreeItem *item = m_form->objectTree()->lookup(it.key());
		if(item && item->widget())
		{
			item->widget()->resize(  m_sizes[item->widget()->name()] );
			if(m_type == SizeToGrid)
				item->widget()->move( m_pos[item->widget()->name()] );
			m_form->setSelectedWidget(item->widget(), true); // We restore selection
		}
	}
}

TQString
AdjustSizeCommand::name() const
{
	switch(m_type)
	{
		case SizeToGrid:
			return i18n("Resize Widgets to Grid");
		case SizeToFit:
			return i18n("Resize Widgets to Fit Contents");
		case SizeToSmallWidth:
			return i18n("Resize Widgets to Narrowest");
		case SizeToBigWidth:
			return i18n("Resize Widgets to Widest");
		case SizeToSmallHeight:
			return i18n("Resize Widgets to Shortest");
		case SizeToBigHeight:
			return i18n("Resize Widgets to Tallest");
		default:
			return TQString();
	}
}

void
AdjustSizeCommand::debug()
{
	kdDebug() << "AdjustSizeCommand: name=\"" << name() << "\" form=" << m_form->widget()->name()
		<< " widgets=" << m_sizes.keys() << endl;
}

// LayoutPropertyCommand

LayoutPropertyCommand::LayoutPropertyCommand(WidgetPropertySet *buf, const TQCString &wname,
	const TQVariant &oldValue, const TQVariant &value)
 : PropertyCommand(buf, wname, oldValue, value, "layout")
{
	m_form = FormManager::self()->activeForm();
	ObjectTreeItem* titem = m_form->objectTree()->lookup(wname);
	if (!titem)
		return; //better this than a crash
	Container *m_container = titem->container();
	// We save the geometry of each wigdet
	for(ObjectTreeItem *it = m_container->objectTree()->children()->first(); it; it = m_container->objectTree()->children()->next())
		m_geometries.insert(it->name().latin1(), it->widget()->geometry());
}

void
LayoutPropertyCommand::execute()
{
	PropertyCommand::execute();
}

void
LayoutPropertyCommand::unexecute()
{
	ObjectTreeItem* titem = m_form->objectTree()->lookup(m_oldvalues.begin().key());
	if (!titem)
		return; //better this than a crash
	Container *m_container = titem->container();
	m_container->setLayout(Container::NoLayout);
	// We put every widget back in its old location
	TQMap<TQCString,TQRect>::ConstIterator endIt = m_geometries.constEnd();
	for(TQMap<TQCString,TQRect>::ConstIterator it = m_geometries.constBegin(); it != endIt; ++it)
	{
		ObjectTreeItem *tree = m_container->form()->objectTree()->lookup(it.key());
		if(tree)
			tree->widget()->setGeometry(it.data());
	}

	PropertyCommand::unexecute();
}

TQString
LayoutPropertyCommand::name() const
{
	return i18n("Change layout of widget \"%1\"").arg(TQString(m_oldvalues.begin().key()));
}

void
LayoutPropertyCommand::debug()
{
	kdDebug() << "LayoutPropertyCommand: name=\"" << name() << "\" oldValue=" << m_oldvalues.keys()
		<< " value=" << m_value << endl;
}

// InsertWidgetCommand

InsertWidgetCommand::InsertWidgetCommand(Container *container)
  : Command()
{
	m_containername = container->widget()->name();
	m_form = container->form();
	m_class = FormManager::self()->selectedClass();
	m_insertRect = container->m_insertRect;
	m_point = container->m_insertBegin;
	m_name = container->form()->objectTree()->generateUniqueName(
		container->form()->library()->namePrefix(m_class).latin1(),
		/*!numberSuffixRequired*/false);
}

InsertWidgetCommand::InsertWidgetCommand(Container *container,
	const TQCString& className, const TQPoint& pos, const TQCString& namePrefix)
  : Command()
{
	m_containername = container->widget()->name();
	m_form = container->form();
	m_class = className;
	//m_insertRect is null (default)
	m_point = pos;
	if (namePrefix.isEmpty()) {
		m_name = container->form()->objectTree()->generateUniqueName(
			container->form()->library()->namePrefix(m_class).latin1() );
	}
	else {
		m_name = container->form()->objectTree()->generateUniqueName(
			namePrefix, false /*!numberSuffixRequired*/ );
	}
}

void
InsertWidgetCommand::execute()
{
	if (!m_form->objectTree())
		return;
	ObjectTreeItem* titem = m_form->objectTree()->lookup(m_containername);
	if (!titem)
		return; //better this than a crash
	Container *m_container = titem->container();
	int options = WidgetFactory::DesignViewMode | WidgetFactory::AnyOrientation;
	if (m_container->form()->library()->internalProperty(m_class, "orientationSelectionPopup")=="1") {
		if(m_insertRect.isValid()) {
			if (m_insertRect.width() < m_insertRect.height()) {
				options |= WidgetFactory::VerticalOrientation;
				options ^= WidgetFactory::AnyOrientation;
			}
			else if (m_insertRect.width() > m_insertRect.height()) {
				options |= WidgetFactory::HorizontalOrientation;
				options ^= WidgetFactory::AnyOrientation;
			}
		}
		if (options & WidgetFactory::AnyOrientation) {
			options ^= WidgetFactory::AnyOrientation;
			options |= m_container->form()->library()->showOrientationSelectionPopup(
				m_class, m_container->m_container,
				m_container->form()->widget()->mapToGlobal(m_point));
			if (options & WidgetFactory::AnyOrientation)
				return; //cancelled
		}
	}
	else
		options |= WidgetFactory::AnyOrientation;

	TQWidget *w = m_container->form()->library()->createWidget(m_class, m_container->m_container, m_name,
		m_container, options);

	if(!w) {
		FormManager::self()->stopInsert();
		WidgetInfo *winfo = m_container->form()->library()->widgetInfoForClassName(m_class);
		KMessageBox::sorry(FormManager::self()->activeForm() ? FormManager::self()->activeForm()->widget() : 0,
				i18n("Could not insert widget of type \"%1\". A problem with widget's creation encountered.")
				.arg(winfo ? winfo->name() : TQString()));
		kdWarning() << "InsertWidgetCommand::execute() ERROR: widget creation failed" << endl;
		return;
	}
//! @todo allow setting this for data view mode as well
	if (m_form->designMode()) {
		//don't generate accelerators for widgets in design mode
		TDEAcceleratorManager::setNoAccel(w);
	}

	// if the insertRect is invalid (ie only one point), we use widget' size hint
	if(( (m_insertRect.width() < 21) && (m_insertRect.height() < 21)))
	{
		TQSize s = w->sizeHint();

		if(s.isEmpty())
			s = TQSize(20, 20); // Minimum size to avoid creating a (0,0) widget
		int x, y;
		if(m_insertRect.isValid())
		{
			x = m_insertRect.x();
			y = m_insertRect.y();
		}
		else
		{
			x = m_point.x();
			y = m_point.y();
		}
		m_insertRect = TQRect(x, y, s.width() + 16/* add some space so more text can be entered*/,
			s.height());
	}
	w->move(m_insertRect.x(), m_insertRect.y());
	w->resize(m_insertRect.width()-1, m_insertRect.height()-1); // -1 is not to hide dots
	w->setStyle(&(m_container->widget()->style()));
	w->setBackgroundOrigin(TQWidget::ParentOrigin);
	w->show();

	FormManager::self()->stopInsert();

	// ObjectTreeItem object already exists for widgets which corresponds to a Container
	// it's already created in Container's constructor
	ObjectTreeItem *item = m_container->form()->objectTree()->lookup(m_name);
	if (!item) { //not yet created...
		m_container->form()->objectTree()->addItem(m_container->m_tree,
			item = new ObjectTreeItem(m_container->form()->library()->displayName(m_class), m_name, w, m_container)
		);
	}
	//assign item for its widget if it supports DesignTimeDynamicChildWidgetHandler interface
	//(e.g. KexiDBAutoField)
	if (m_form->designMode() && dynamic_cast<DesignTimeDynamicChildWidgetHandler*>(w)) {
		dynamic_cast<DesignTimeDynamicChildWidgetHandler*>(w)->assignItem(item);
	}

	// We add the autoSaveProperties in the modifProp list of the ObjectTreeItem, so that they are saved later
	TQValueList<TQCString> list(m_container->form()->library()->autoSaveProperties(w->className()));

	TQValueList<TQCString>::ConstIterator endIt = list.constEnd();
	for(TQValueList<TQCString>::ConstIterator it = list.constBegin(); it != endIt; ++it)
		item->addModifiedProperty(*it, w->property(*it));

	m_container->reloadLayout(); // reload the layout to take the new wigdet into account

	m_container->setSelectedWidget(w, false);
	if (m_container->form()->library()->internalProperty(w->className(),
			"dontStartEditingOnInserting").isEmpty())
	{
		m_container->form()->library()->startEditing(
			w->className(), w, item->container() ? item->container() : m_container); // we edit the widget on creation
	}
//! @todo update widget's width for entered text's metrics
	kdDebug() << "Container::eventFilter(): widget added " << this << endl;
}

void
InsertWidgetCommand::unexecute()
{
	ObjectTreeItem* titem = m_form->objectTree()->lookup(m_name);
	if (!titem)
		return; //better this than a crash
	TQWidget *m_widget = titem->widget();
	Container *m_container = m_form->objectTree()->lookup(m_containername)->container();
	m_container->deleteWidget(m_widget);
}

TQString
InsertWidgetCommand::name() const
{
	if(!m_name.isEmpty())
		return i18n("Insert widget \"%1\"").arg(TQString(m_name));
	else
		return i18n("Insert widget");
}

void
InsertWidgetCommand::debug()
{
	kdDebug() << "InsertWidgetCommand: name=\"" << name() << "\" generatedName=" << m_name
		<< " container=" << m_containername
		<< " form=" << m_form->widget()->name() << " class=" << m_class
		<< " rect=" << m_insertRect << " pos=" << m_point << endl;
}

/// CreateLayoutCommand ///////////////

CreateLayoutCommand::CreateLayoutCommand(int layoutType, WidgetList &list, Form *form)
 : m_form(form), m_type(layoutType)
{
	WidgetList *m_list=0;
	switch(layoutType)
	{
		case Container::HBox:
		case Container::Grid:
		case Container::HSplitter:
		case Container::HFlow:
			m_list = new HorWidgetList(form->toplevelContainer()->widget()); break;
		case Container::VBox:
		case Container::VSplitter:
		case Container::VFlow:
			m_list = new VerWidgetList(form->toplevelContainer()->widget()); break;
	}
	for(TQWidget *w = list.first(); w; w = list.next())
		m_list->append(w);
	m_list->sort(); // we sort them now, before creating the layout

	for(TQWidget *w = m_list->first(); w; w = m_list->next())
		m_pos.insert(w->name(), w->geometry());
	ObjectTreeItem *item = form->objectTree()->lookup(m_list->first()->name());
	if(item && item->parent()->container())
		m_containername = item->parent()->name();
	delete m_list;
}

void
CreateLayoutCommand::execute()
{
	WidgetLibrary *lib = m_form->library();
	if(!lib)
		return;
	ObjectTreeItem* titem = m_form->objectTree()->lookup(m_containername);
	Container *container = titem ? titem->container() : 0;
	if(!container)
		container = m_form->toplevelContainer(); // use toplevelContainer by default

	TQCString classname;
	switch(m_type)  {
		case Container::HSplitter: case Container::VSplitter:
			classname = "TQSplitter"; break;
		default:
			classname = Container::layoutTypeToString(m_type).latin1();
	}

	if(m_name.isEmpty())// the name must be generated only once
		m_name = m_form->objectTree()->generateUniqueName(classname);

	TQWidget *w = lib->createWidget(classname, container->widget(), m_name.latin1(), container);
//! @todo allow setting this for data view mode as well
	if (w) {
		if (m_form->designMode()) {
			//don't generate accelerators for widgets in design mode
			TDEAcceleratorManager::setNoAccel(w);
		}
	}
	ObjectTreeItem *tree = w ? m_form->objectTree()->lookup(w->name()) : 0;
	if(!tree)
		return;

	container->setSelectedWidget(0, false);
	w->move(m_pos.begin().data().topLeft()); // we move the layout at the position of the topleft widget
	// sizeHint of these widgets depends on geometry, so give them appropriate geometry
	if(m_type == Container::HFlow)
		w->resize( TQSize(700, 20) );
	else if(m_type == Container::VFlow)
		w->resize( TQSize(20, 700));
	w->show();

	// We reparent every widget to the Layout and insert them into it
	TQMap<TQCString,TQRect>::ConstIterator endIt = m_pos.constEnd();
	for(TQMap<TQCString,TQRect>::ConstIterator it = m_pos.constBegin(); it != endIt; ++it)
	{
		ObjectTreeItem *item = m_form->objectTree()->lookup(it.key());
		if(item && item->widget())
		{
			item->widget()->reparent(w, item->widget()->pos(), true);
			item->eventEater()->setContainer(tree->container());
			m_form->objectTree()->reparent(item->name(), m_name);
		}
	}

	if(m_type == Container::HSplitter)
		((TQSplitter*)w)->setOrientation(TQt::Horizontal);
	else if(m_type == Container::VSplitter)
		((TQSplitter*)w)->setOrientation(TQt::Vertical);
	else if(tree->container()) {
		tree->container()->setLayout((Container::LayoutType)m_type);
		w->resize(tree->container()->layout()->sizeHint()); // the layout doesn't have its own size
	}

	container->setSelectedWidget(w, false);
	FormManager::self()->windowChanged(m_form->widget()); // to reload the ObjectTreeView
}

void
CreateLayoutCommand::unexecute()
{
	ObjectTreeItem *parent = m_form->objectTree()->lookup(m_containername);
	if(!parent)
		parent = m_form->objectTree();

	// We reparent every widget to the Container and take them out of the layout
	TQMap<TQCString,TQRect>::ConstIterator endIt = m_pos.constEnd();
	for(TQMap<TQCString,TQRect>::ConstIterator it = m_pos.constBegin(); it != endIt; ++it)
	{
		ObjectTreeItem *item = m_form->objectTree()->lookup(it.key());
		if(item && item->widget())
		{
			item->widget()->reparent(parent->widget(), TQPoint(0,0), true);
			item->eventEater()->setContainer(parent->container());
			if(m_pos[it.key()].isValid())
				item->widget()->setGeometry(m_pos[it.key()]);
			m_form->objectTree()->reparent(item->name(), m_containername);
		}
	}

	if(!parent->container())
		return;
	ObjectTreeItem* titem = m_form->objectTree()->lookup(m_name);
	if (!titem)
		return; //better this than a crash
	TQWidget *w = titem->widget();
	parent->container()->deleteWidget(w); // delete the layout widget
	FormManager::self()->windowChanged(m_form->widget()); // to reload ObjectTreeView
}

TQString
CreateLayoutCommand::name() const
{
	switch(m_type)
	{
		case Container::HBox:
			return i18n("Group Widgets Horizontally");
		case Container::VBox:
			return i18n("Group Widgets Vertically");
		case Container::Grid:
			return i18n("Group Widgets in a Grid");
		case Container::HSplitter:
			return i18n("Group Widgets Horizontally in a Splitter");
		case Container::VSplitter:
			return i18n("Group Widgets Vertically in a Splitter");
		case Container::HFlow:
			return i18n("Group Widgets By Rows");
		case Container::VFlow:
			return i18n("Group Widgets Vertically By Columns");
		default:
			return i18n("Group widgets");
	}
}

void
CreateLayoutCommand::debug()
{
	kdDebug() << "CreateLayoutCommand: name=\"" << name() << "\" generatedName=" << m_name
		<< " widgets=" << m_pos.keys() << " container=" << m_containername
		<< " form=" << m_form->widget()->name() << endl;
}

/// BreakLayoutCommand ///////////////

BreakLayoutCommand::BreakLayoutCommand(Container *container)
 : CreateLayoutCommand()
{
	m_containername = container->toplevel()->widget()->name();
	m_name = container->widget()->name();
	m_form = container->form();
	m_type = container->layoutType();

	for(ObjectTreeItem *tree = container->objectTree()->children()->first(); tree; tree = container->objectTree()->children()->next())
	{
		TQRect r(container->widget()->mapTo(container->widget()->parentWidget(), tree->widget()->pos()), tree->widget()->size());
		m_pos.insert(tree->widget()->name(), r);
	}
}

void
BreakLayoutCommand::execute()
{
	CreateLayoutCommand::unexecute();
}

void
BreakLayoutCommand::unexecute()
{
	CreateLayoutCommand::execute();
}

TQString
BreakLayoutCommand::name() const
{
	return i18n("Break Layout: \"%1\"").arg(m_name);
}

void
BreakLayoutCommand::debug()
{
	kdDebug() << "BreakLayoutCommand: name=\"" << name()
		<< " widgets=" << m_pos.keys() << " container=" << m_containername
		<< " form=" << m_form->widget()->name() << endl;
}

// PasteWidgetCommand

PasteWidgetCommand::PasteWidgetCommand(TQDomDocument &domDoc, Container *container, const TQPoint& p)
 : m_point(p)
{
	m_data = domDoc.toCString();
	m_containername = container->widget()->name();
	m_form = container->form();

	if(domDoc.namedItem("UI").firstChild().nextSibling().toElement().tagName() != "widget")
		return;

	TQRect boundingRect;
	for(TQDomNode n = domDoc.namedItem("UI").firstChild(); !n.isNull(); n = n.nextSibling()) // more than one widget
	{
		if(n.toElement().tagName() != "widget")
			continue;
		TQDomElement el = n.toElement();

		TQDomElement rect;
		for(TQDomNode n = el.firstChild(); !n.isNull(); n = n.nextSibling())
		{
			if((n.toElement().tagName() == "property") && (n.toElement().attribute("name") == "geometry"))
				rect = n.firstChild().toElement();
		}

		TQDomElement x = rect.namedItem("x").toElement();
		TQDomElement y = rect.namedItem("y").toElement();
		TQDomElement wi = rect.namedItem("width").toElement();
		TQDomElement h = rect.namedItem("height").toElement();

		int rx = x.text().toInt();
		int ry = y.text().toInt();
		int rw = wi.text().toInt();
		int rh = h.text().toInt();
		TQRect r(rx, ry, rw, rh);
		boundingRect = boundingRect.unite(r);
	}

	m_point = m_point - boundingRect.topLeft();
}

void
PasteWidgetCommand::execute()
{
	ObjectTreeItem* titem = m_form->objectTree()->lookup(m_containername);
	if (!titem)
		return; //better this than a crash
	Container *container = titem->container();
	TQString errMsg;
	int errLine;
	int errCol;
	TQDomDocument domDoc("UI");
	bool parsed = domDoc.setContent(m_data, false, &errMsg, &errLine, &errCol);

	if(!parsed)
	{
		kdDebug() << "WidgetWatcher::load(): " << errMsg << endl;
		kdDebug() << "WidgetWatcher::load(): line: " << errLine << " col: " << errCol << endl;
		return;
	}

	//FormIO::setCurrentForm(m_container->form());

	kdDebug() << domDoc.toString() << endl;
	if(!domDoc.namedItem("UI").hasChildNodes()) // nothing in the doc
		return;
	if(domDoc.namedItem("UI").firstChild().nextSibling().toElement().tagName() != "widget") // only one widget, so we can paste it at cursor pos
	{
		TQDomElement el = domDoc.namedItem("UI").firstChild().toElement();
		fixNames(el);
		if(m_point.isNull())
			fixPos(el, container);
		else
			changePos(el, m_point);

		m_form->setInteractiveMode(false);
		FormIO::loadWidget(container, el);
		m_form->setInteractiveMode(true);
	}
	else for(TQDomNode n = domDoc.namedItem("UI").firstChild(); !n.isNull(); n = n.nextSibling()) // more than one widget
	{
		if(n.toElement().tagName() != "widget")
			continue;
		TQDomElement el = n.toElement();
		fixNames(el);
		if(!m_point.isNull())
			moveWidgetBy(el, container, m_point);
		else {
			fixPos(el, container);
			kdDebug() << "jdkjfldfksmfkdfjmqdsklfjdkkfmsqfksdfsm" << endl;
		}

		m_form->setInteractiveMode(false);
		FormIO::loadWidget(container, el);
		m_form->setInteractiveMode(true);
	}

	//FormIO::setCurrentForm(0);
	m_names.clear();
	// We store the names of all the created widgets, to delete them later
	for(TQDomNode n = domDoc.namedItem("UI").firstChild(); !n.isNull(); n = n.nextSibling())
	{
		if(n.toElement().tagName() != "widget")
			continue;
		for(TQDomNode m = n.firstChild(); !m.isNull(); n = m.nextSibling())
		{
			if((m.toElement().tagName() == "property") && (m.toElement().attribute("name") == "name"))
			{
				m_names.append(m.toElement().text());
				break;
			}
		}
	}

	container->form()->selectFormWidget();
	TQStringList::ConstIterator endIt = m_names.constEnd();
	for(TQStringList::ConstIterator it = m_names.constBegin(); it != endIt; ++it) // We select all the pasted widgets
	{
		ObjectTreeItem *item = m_form->objectTree()->lookup(*it);
		if(item)
			container->setSelectedWidget(item->widget(), true);
	}
}

void
PasteWidgetCommand::unexecute()
{
	ObjectTreeItem* titem = m_form->objectTree()->lookup(m_containername);
	if (!titem)
		return; //better this than a crash
	Container *container = titem->container();
	// We just delete all the widgets we have created
	TQStringList::ConstIterator endIt = m_names.constEnd();
	for(TQStringList::ConstIterator it = m_names.constBegin(); it != endIt; ++it)
	{
		ObjectTreeItem* titem = container->form()->objectTree()->lookup(*it);
		if (!titem)
			continue; //better this than a crash
		TQWidget *w = titem->widget();
		container->deleteWidget(w);
	}
}

TQString
PasteWidgetCommand::name() const
{
	return i18n("Paste");
}

void
//TQDomElement
PasteWidgetCommand::changePos(TQDomElement &el, const TQPoint &newpos)
{
	//TQDomElement el = widg.cloneNode(true).toElement();
	TQDomElement rect;
	// Find the widget geometry if there is one
	for(TQDomNode n = el.firstChild(); !n.isNull(); n = n.nextSibling())
	{
		if((n.toElement().tagName() == "property") && (n.toElement().attribute("name") == "geometry"))
			rect = n.firstChild().toElement();
	}

	TQDomElement x = rect.namedItem("x").toElement();
	x.removeChild(x.firstChild());
	TQDomText valueX = el.ownerDocument().createTextNode(TQString::number(newpos.x()));
	x.appendChild(valueX);

	TQDomElement y = rect.namedItem("y").toElement();
	y.removeChild(y.firstChild());
	TQDomText valueY = el.ownerDocument().createTextNode(TQString::number(newpos.y()));
	y.appendChild(valueY);

	//return el;
}

void
PasteWidgetCommand::fixPos(TQDomElement &el, Container *container)
{
/*	TQDomElement rect;
	for(TQDomNode n = el.firstChild(); !n.isNull(); n = n.nextSibling())
	{
		if((n.toElement().tagName() == "property") && (n.toElement().attribute("name") == "geometry"))
			rect = n.firstChild().toElement();
	}

	TQDomElement x = rect.namedItem("x").toElement();
	TQDomElement y = rect.namedItem("y").toElement();
	TQDomElement wi = rect.namedItem("width").toElement();
	TQDomElement h = rect.namedItem("height").toElement();

	int rx = x.text().toInt();
	int ry = y.text().toInt();
	int rw = wi.text().toInt();
	int rh = h.text().toInt();
	TQRect r(rx, ry, rw, rh);

	TQWidget *w = m_form->widget()->childAt(r.x() + 6, r.y() + 6, false);
	if(!w)
		return;

	while((w->geometry() == r) && (w != 0))// there is already a widget there, with the same size
	{
		w = m_form->widget()->childAt(w->x() + 16, w->y() + 16, false);
		r.moveBy(10,10);
	}

	// the pasted wigdet should stay inside container's boundaries
	if(r.x() < 0)
		r.moveLeft(0);
	else if(r.right() > container->widget()->width())
		r.moveLeft(container->widget()->width() - r.width());

	if(r.y() < 0)
		r.moveTop(0);
	else if(r.bottom() > container->widget()->height())
		r.moveTop(container->widget()->height() - r.height());

	if(r != TQRect(rx, ry, rw, rh))
		//return el;
	//else
		changePos(el, TQPoint(r.x(), r.y()));
*/
	moveWidgetBy(el, container, TQPoint(0, 0));
}

void
PasteWidgetCommand::moveWidgetBy(TQDomElement &el, Container *container, const TQPoint &p)
{
	TQDomElement rect;
	for(TQDomNode n = el.firstChild(); !n.isNull(); n = n.nextSibling())
	{
		if((n.toElement().tagName() == "property") && (n.toElement().attribute("name") == "geometry"))
			rect = n.firstChild().toElement();
	}

	TQDomElement x = rect.namedItem("x").toElement();
	TQDomElement y = rect.namedItem("y").toElement();
	TQDomElement wi = rect.namedItem("width").toElement();
	TQDomElement h = rect.namedItem("height").toElement();

	int rx = x.text().toInt();
	int ry = y.text().toInt();
	int rw = wi.text().toInt();
	int rh = h.text().toInt();
	TQRect r(rx + p.x(), ry + p.y(), rw, rh);
	kdDebug() << "Moving widget by " << p << " from " << rx << "  " << ry << " to " << r.topLeft() << endl;

	TQWidget *w = m_form->widget()->childAt(r.x() + 6, r.y() + 6, false);

	while(w && (w->geometry() == r))// there is already a widget there, with the same size
	{
		w = m_form->widget()->childAt(w->x() + 16, w->y() + 16, false);
		r.moveBy(10,10);
	}

	// the pasted wigdet should stay inside container's boundaries
	if(r.x() < 0)
		r.moveLeft(0);
	else if(r.right() > container->widget()->width())
		r.moveLeft(container->widget()->width() - r.width());

	if(r.y() < 0)
		r.moveTop(0);
	else if(r.bottom() > container->widget()->height())
		r.moveTop(container->widget()->height() - r.height());

	if(r != TQRect(rx, ry, rw, rh))
		//return el;
	//else
		changePos(el, TQPoint(r.x(), r.y()));
}

void
PasteWidgetCommand::fixNames(TQDomElement &el)
{
	TQString wname;
	for(TQDomNode n = el.firstChild(); !n.isNull(); n = n.nextSibling())
	{
		if((n.toElement().tagName() == "property") && (n.toElement().attribute("name") == "name"))
		{
			wname = n.toElement().text();
			while(m_form->objectTree()->lookup(wname)) // name already exists
			{
				bool ok;
				int num = wname.right(1).toInt(&ok, 10);
				if(ok)
					wname = wname.left(wname.length()-1) + TQString::number(num+1);
				else
					wname += "2";
			}
			if(wname != n.toElement().text()) // we change the name, so we recreate the element
			{
				n.removeChild(n.firstChild());
				TQDomElement type = el.ownerDocument().createElement("string");
				TQDomText valueE = el.ownerDocument().createTextNode(wname);
				type.appendChild(valueE);
				n.toElement().appendChild(type);
			}

		}
		if(n.toElement().tagName() == "widget") // fix child widgets names
		{
			TQDomElement child = n.toElement();
			fixNames(child);
		}
	}
}

void
PasteWidgetCommand::debug()
{
	kdDebug() << "PasteWidgetCommand: pos=" << m_point
		<< " widgets=" << m_names << " container=" << m_containername
		<< " form=" << m_form->widget()->name()
		<< " data=\"" << m_data.left(80) << "...\"" << endl;
}

// DeleteWidgetCommand

DeleteWidgetCommand::DeleteWidgetCommand(WidgetList &list, Form *form)
 : Command(), m_form(form)
{
	m_domDoc = TQDomDocument("UI");
	m_domDoc.appendChild(m_domDoc.createElement("UI"));

	TQDomElement parent = m_domDoc.namedItem("UI").toElement();

	//for(TQWidget *w = list.first(); w; w = list.next())
	/*for(WidgetListIterator it(list); it.current() != 0; ++it)
	{
		TQWidget *w = it.current();
		// Don't delete tabwidget or widgetstack pages
		if(w->parentWidget()->inherits("TQWidgetStack"))
		{
			list.remove(w);
			continue;
		}
	}*/
	removeChildrenFromList(list);

	for(WidgetListIterator it(list); it.current() != 0; ++it)
	{
		ObjectTreeItem *item = m_form->objectTree()->lookup(it.current()->name());
		if (!item)
			return;

		// We need to store both parentContainer and parentWidget as they may be different (eg for TabWidget page)
		m_containers.insert(item->name().latin1(), m_form->parentContainer(item->widget())->widget()->name());
		m_parents.insert(item->name().latin1(), item->parent()->name().latin1());
		FormIO::saveWidget(item, parent, m_domDoc);
		form->connectionBuffer()->saveAllConnectionsForWidget(item->widget()->name(), m_domDoc);
	}

	FormIO::cleanClipboard(parent);
}

void
DeleteWidgetCommand::execute()
{
	Container *containerToSelect = 0;

	TQMap<TQCString,TQCString>::ConstIterator endIt = m_containers.constEnd();
	for(TQMap<TQCString,TQCString>::ConstIterator  it = m_containers.constBegin(); it != endIt; ++it)
	{
		ObjectTreeItem *item = m_form->objectTree()->lookup(it.key());
		if (!item || !item->widget())
			continue;

		Container *cont = m_form->parentContainer(item->widget());
		if (!containerToSelect)
			containerToSelect = cont;
		cont->deleteWidget(item->widget());
	}
	//now we've nothing selecte: select parent container
	if (containerToSelect)
		m_form->setSelectedWidget( containerToSelect->widget() );
}

void
DeleteWidgetCommand::unexecute()
{
	TQCString wname;
	m_form->setInteractiveMode(false);
	for(TQDomNode n = m_domDoc.namedItem("UI").firstChild(); !n.isNull(); n = n.nextSibling())
	{
		if(n.toElement().tagName() == "connections") // restore the widget connections
			m_form->connectionBuffer()->load(n);
		if(n.toElement().tagName() != "widget")
			continue;
		// We need first to know the name of the widget
		for(TQDomNode m = n.firstChild(); !m.isNull(); n = m.nextSibling())
		{
			if((m.toElement().tagName() == "property") && (m.toElement().attribute("name") == "name"))
			{
				wname = m.toElement().text().latin1();
				break;
			}
		}

		ObjectTreeItem* titem = m_form->objectTree()->lookup(m_containers[wname]);
		if (!titem)
			return; //better this than a crash
		Container *cont = titem->container();
		ObjectTreeItem *parent = m_form->objectTree()->lookup(m_parents[wname]);
		TQDomElement widg = n.toElement();
		if(parent)
			FormIO::loadWidget(cont, widg, parent->widget());
		else
			FormIO::loadWidget(cont, widg);
	}
	m_form->setInteractiveMode(true);
}

TQString
DeleteWidgetCommand::name() const
{
	return i18n("Delete widget");
}

void
DeleteWidgetCommand::debug()
{
	kdDebug() << "DeleteWidgetCommand: containers=" << m_containers.keys()
		<< " parents=" << m_parents.keys() << " form=" << m_form->widget()->name() << endl;
}

// CutWidgetCommand

CutWidgetCommand::CutWidgetCommand(WidgetList &list, Form *form)
 : DeleteWidgetCommand(list, form)
{}

void
CutWidgetCommand::execute()
{
	DeleteWidgetCommand::execute();
	m_data = FormManager::self()->m_domDoc.toCString();
	FormManager::self()->m_domDoc.setContent(m_domDoc.toCString());
}

void
CutWidgetCommand::unexecute()
{
	DeleteWidgetCommand::unexecute();
	FormManager::self()->m_domDoc.setContent(m_data);
}

TQString
CutWidgetCommand::name() const
{
	return i18n("Cut");
}

void
CutWidgetCommand::debug()
{
	kdDebug() << "CutWidgetCommand: containers=" << m_containers.keys()
		<< " parents=" << m_parents.keys() << " form=" << m_form->widget()->name()
		<< " data=\"" << m_data.left(80) << "...\"" << endl;
}

// CommandGroup

namespace KFormDesigner {
class CommandGroup::SubCommands : public KMacroCommand
{
	public:
		SubCommands( const TQString & name )
		 : KMacroCommand(name)
		{
		}
		const TQPtrList<KCommand>& commands() const { return m_commands; }
};
}

CommandGroup::CommandGroup( const TQString & name, WidgetPropertySet *propSet )
	: Command()
	, m_subCommands(new SubCommands(name))
	, m_propSet(propSet)
{
}

CommandGroup::~CommandGroup()
{
	delete m_subCommands;
}

const TQPtrList<KCommand>& CommandGroup::commands() const
{
	return m_subCommands->commands();
}

void CommandGroup::addCommand(KCommand *command, bool allowExecute)
{
	if (!command)
		return;

	m_subCommands->addCommand(command);
	if (!allowExecute)
		m_commandsShouldntBeExecuted.insert(command, (char*)1);
}

void CommandGroup::execute()
{
	FormManager::self()->blockPropertyEditorUpdating(this);
	for (TQPtrListIterator<KCommand> it(m_subCommands->commands()); it.current(); ++it) {
		if (!m_commandsShouldntBeExecuted[it.current()])
			it.current()->execute();
	}
	FormManager::self()->unblockPropertyEditorUpdating(this, m_propSet);
}

void CommandGroup::unexecute()
{
	FormManager::self()->blockPropertyEditorUpdating(this);
	m_subCommands->unexecute();
	FormManager::self()->unblockPropertyEditorUpdating(this, m_propSet);
}

TQString CommandGroup::name() const
{
	return m_subCommands->name();
}

void CommandGroup::resetAllowExecuteFlags()
{
	m_commandsShouldntBeExecuted.clear();
}

void
CommandGroup::debug()
{
	kdDebug() << "*CommandGroup: name=\"" << name() << "\" #=" << m_subCommands->commands().count() << endl;
	uint i = 1;
	for (TQPtrListIterator<KCommand> it(m_subCommands->commands()); it.current(); ++it, i++) {
		kdDebug() << "#" << i << ":"
			<< (m_commandsShouldntBeExecuted[it.current()] ? "!" : "") << "allowExecute:" << endl;
		if (dynamic_cast<Command*>(it.current()))
			dynamic_cast<Command*>(it.current())->debug();
		else if (dynamic_cast<CommandGroup*>(it.current()))
			dynamic_cast<CommandGroup*>(it.current())->debug();
		else
			kdDebug() << "(other KCommand)" << endl;
	}
	kdDebug() << "End of CommandGroup" << endl;
}
