diff options
author | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-01-20 01:29:50 +0000 |
---|---|---|
committer | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-01-20 01:29:50 +0000 |
commit | 8362bf63dea22bbf6736609b0f49c152f975eb63 (patch) | |
tree | 0eea3928e39e50fae91d4e68b21b1e6cbae25604 /kexi/formeditor/commands.cpp | |
download | koffice-8362bf63dea22bbf6736609b0f49c152f975eb63.tar.gz koffice-8362bf63dea22bbf6736609b0f49c152f975eb63.zip |
Added old abandoned KDE3 version of koffice
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/koffice@1077364 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'kexi/formeditor/commands.cpp')
-rw-r--r-- | kexi/formeditor/commands.cpp | 1601 |
1 files changed, 1601 insertions, 0 deletions
diff --git a/kexi/formeditor/commands.cpp b/kexi/formeditor/commands.cpp new file mode 100644 index 00000000..ca4f0f20 --- /dev/null +++ b/kexi/formeditor/commands.cpp @@ -0,0 +1,1601 @@ +/* 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 <qdom.h> +#include <qwidget.h> +#include <qlayout.h> +#include <qlabel.h> +#include <qsplitter.h> +#include <qmetaobject.h> + +#include <kdebug.h> +#include <klocale.h> +#include <kpopupmenu.h> +#include <kmessagebox.h> +#include <kaccelmanager.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 QCString &wname, + const QVariant &oldValue, const QVariant &value, const QCString &property) + : Command(), m_propSet(set), m_value(value), m_property(property) +{ + m_oldvalues.insert(wname, oldValue); +} + +PropertyCommand::PropertyCommand(WidgetPropertySet *set, const QMap<QCString, QVariant> &oldvalues, + const QVariant &value, const QCString &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 QVariant &value) +{ + m_value = value; + emit FormManager::self()->dirty(FormManager::self()->activeForm()); +} + +void +PropertyCommand::execute() +{ + FormManager::self()->activeForm()->selectFormWidget(); + m_propSet->setUndoing(true); + + QMap<QCString, QVariant>::ConstIterator endIt = m_oldvalues.constEnd(); + for(QMap<QCString, QVariant>::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); + + QMap<QCString, QVariant>::ConstIterator endIt = m_oldvalues.constEnd(); + for(QMap<QCString, QVariant>::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 + QWidget *widg = item->widget(); + FormManager::self()->activeForm()->setSelectedWidget(widg, true); + //m_propSet->setSelectedWidget(widg, true); + + WidgetWithSubpropertiesInterface* subpropIface = dynamic_cast<WidgetWithSubpropertiesInterface*>(widg); + QWidget *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); +} + +QString +PropertyCommand::name() const +{ + if(m_oldvalues.count() >= 2) + return i18n("Change \"%1\" property for multiple widgets" ).arg(m_property); + else + return i18n("Change \"%1\" property for widget \"%2\"" ).arg(m_property).arg(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 QStringList &names, const QPoint& 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(); + + QStringList::ConstIterator endIt = m_names.constEnd(); + // We move every widget in our list by (dx, dy) + for(QStringList::ConstIterator it = m_names.constBegin(); it != endIt; ++it) + { + ObjectTreeItem* item = FormManager::self()->activeForm()->objectTree()->lookup(*it); + if (!item) + continue; //better this than a crash + QWidget *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(); + + QStringList::ConstIterator endIt = m_names.constEnd(); + // We move every widget in our list by (-dx, -dy) to undo the move + for(QStringList::ConstIterator it = m_names.constBegin(); it != endIt; ++it) + { + ObjectTreeItem* item = FormManager::self()->activeForm()->objectTree()->lookup(*it); + if (!item) + continue; //better this than a crash + QWidget *w = item->widget(); + w->move(w->x() - dx, w->y() - dy); + } + m_propSet->setUndoing(false); +} + +void +GeometryPropertyCommand::setPos(const QPoint& pos) +{ + m_pos = pos; + emit FormManager::self()->dirty(FormManager::self()->activeForm()); +} + +QString +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(QWidget *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(); + QWidget *parentWidget = m_form->selectedWidgets()->first()->parentWidget(); + int tmpx, tmpy; + + WidgetList list; + QMap<QCString, QPoint>::ConstIterator endIt = m_pos.constEnd(); + for(QMap<QCString, QPoint>::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(QWidget *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(QWidget *w = list.first(); w; w = list.next()) + { + if(w->x() < tmpx) + tmpx = w->x(); + } + + for(QWidget *w = list.first(); w; w = list.next()) + w->move(tmpx, w->y()); + break; + } + + case AlignToRight: + { + tmpx = 0; + for(QWidget *w = list.first(); w; w = list.next()) + { + if(w->x() + w->width() > tmpx) + tmpx = w->x() + w->width(); + } + + for(QWidget *w = list.first(); w; w = list.next()) + w->move(tmpx - w->width(), w->y()); + break; + } + + case AlignToTop: + { + tmpy = parentWidget->height(); + for(QWidget *w = list.first(); w; w = list.next()) + { + if(w->y() < tmpy) + tmpy = w->y(); + } + + for(QWidget *w = list.first(); w; w = list.next()) + w->move(w->x(), tmpy); + break; + } + + case AlignToBottom: + { + tmpy = 0; + for(QWidget *w = list.first(); w; w = list.next()) + { + if(w->y() + w->height() > tmpy) + tmpy = w->y() + w->height(); + } + + for(QWidget *w = list.first(); w; w = list.next()) + w->move(w->x(), tmpy - w->height()); + break; + } + + default: + return; + } + + // We restore selection + for(QWidget *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 + QMap<QCString, QPoint>::ConstIterator endIt = m_pos.constEnd(); + for(QMap<QCString, QPoint>::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 + } +} + +QString +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 QString::null; + } +} + +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(QWidget *w = list.first(); w; w = list.next()) + { + if(w->parentWidget() && w->parentWidget()->isA("QWidgetStack")) + { + w = w->parentWidget(); // widget is WidgetStack page + if(w->parentWidget() && w->parentWidget()->inherits("QTabWidget")) // 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; + QMap<QCString, QSize>::ConstIterator endIt = m_sizes.constEnd(); + for(QMap<QCString, QSize>::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(QWidget *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(QWidget *w = list.first(); w; w = list.next()) { + ObjectTreeItem *item = m_form->objectTree()->lookup(w->name()); + if(item && !item->children()->isEmpty()) { // container + QSize 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 { + QSize sizeHint(w->sizeHint()); + if (sizeHint.isValid()) + w->resize(sizeHint); + } + } + break; + } + + case SizeToSmallWidth: + { + for(QWidget *w = list.first(); w; w = list.next()) + { + if((tmpw == 0) || (w->width() < tmpw)) + tmpw = w->width(); + } + + for(QWidget *w = list.first(); w; w = list.next()) + { + if(tmpw != w->width()) + w->resize(tmpw, w->height()); + } + break; + } + + case SizeToBigWidth: + { + for(QWidget *w = list.first(); w; w = list.next()) + { + if(w->width() > tmpw) + tmpw = w->width(); + } + + for(QWidget *w = list.first(); w; w = list.next()) + { + if(tmpw != w->width()) + w->resize(tmpw, w->height()); + } + break; + } + + case SizeToSmallHeight: + { + for(QWidget *w = list.first(); w; w = list.next()) + { + if((tmph == 0) || (w->height() < tmph)) + tmph = w->height(); + } + + for(QWidget *w = list.first(); w; w = list.next()) + { + if(tmph != w->height()) + w->resize(w->width(), tmph); + } + break; + } + + case SizeToBigHeight: + { + for(QWidget *w = list.first(); w; w = list.next()) + { + if(w->height() > tmph) + tmph = w->height(); + } + + for(QWidget *w = list.first(); w; w = list.next()) + { + if(tmph != w->height()) + w->resize(w->width(), tmph); + } + break; + } + + default: + break; + } + + // We restore selection + for(QWidget *w = list.first(); w; w = list.next()) + m_form->setSelectedWidget(w, true); +} + +QSize +AdjustSizeCommand::getSizeFromChildren(ObjectTreeItem *item) +{ + if(!item->container()) // multi pages containers (eg tabwidget) + { + QSize 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 = QMAX(tmpw, tree->widget()->geometry().right()); + tmph = QMAX(tmph, tree->widget()->geometry().bottom()); + } + + return QSize(tmpw, tmph) + QSize(10, 10); +} + +void +AdjustSizeCommand::unexecute() +{ + // To avoid creation of GeometryPropertyCommand + m_form->selectFormWidget(); + // We resize widgets to their original size + QMap<QCString, QSize>::ConstIterator endIt = m_sizes.constEnd(); + for(QMap<QCString, QSize>::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 + } + } +} + +QString +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 QString::null; + } +} + +void +AdjustSizeCommand::debug() +{ + kdDebug() << "AdjustSizeCommand: name=\"" << name() << "\" form=" << m_form->widget()->name() + << " widgets=" << m_sizes.keys() << endl; +} + +// LayoutPropertyCommand + +LayoutPropertyCommand::LayoutPropertyCommand(WidgetPropertySet *buf, const QCString &wname, + const QVariant &oldValue, const QVariant &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 + QMap<QCString,QRect>::ConstIterator endIt = m_geometries.constEnd(); + for(QMap<QCString,QRect>::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(); +} + +QString +LayoutPropertyCommand::name() const +{ + return i18n("Change layout of widget \"%1\"").arg(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 QCString& className, const QPoint& pos, const QCString& 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; + + QWidget *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() : QString::null)); + kdWarning() << "InsertWidgetCommand::execute() ERROR: widget creation failed" << endl; + return; + } +#if KDE_VERSION >= KDE_MAKE_VERSION(3,4,0) +//! @todo allow setting this for data view mode as well + if (m_form->designMode()) { + //don't generate accelerators for widgets in design mode + KAcceleratorManager::setNoAccel(w); + } +#endif + + // if the insertRect is invalid (ie only one point), we use widget' size hint + if(( (m_insertRect.width() < 21) && (m_insertRect.height() < 21))) + { + QSize s = w->sizeHint(); + + if(s.isEmpty()) + s = QSize(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 = QRect(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(QWidget::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 + QValueList<QCString> list(m_container->form()->library()->autoSaveProperties(w->className())); + + QValueList<QCString>::ConstIterator endIt = list.constEnd(); + for(QValueList<QCString>::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 + QWidget *m_widget = titem->widget(); + Container *m_container = m_form->objectTree()->lookup(m_containername)->container(); + m_container->deleteWidget(m_widget); +} + +QString +InsertWidgetCommand::name() const +{ + if(!m_name.isEmpty()) + return i18n("Insert widget \"%1\"").arg(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(QWidget *w = list.first(); w; w = list.next()) + m_list->append(w); + m_list->sort(); // we sort them now, before creating the layout + + for(QWidget *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 + + QCString classname; + switch(m_type) { + case Container::HSplitter: case Container::VSplitter: + classname = "QSplitter"; 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); + + QWidget *w = lib->createWidget(classname, container->widget(), m_name.latin1(), container); +#if KDE_VERSION >= KDE_MAKE_VERSION(3,4,0) +//! @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 + KAcceleratorManager::setNoAccel(w); + } + } +#endif + 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( QSize(700, 20) ); + else if(m_type == Container::VFlow) + w->resize( QSize(20, 700)); + w->show(); + + // We reparent every widget to the Layout and insert them into it + QMap<QCString,QRect>::ConstIterator endIt = m_pos.constEnd(); + for(QMap<QCString,QRect>::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) + ((QSplitter*)w)->setOrientation(QSplitter::Horizontal); + else if(m_type == Container::VSplitter) + ((QSplitter*)w)->setOrientation(QSplitter::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 + QMap<QCString,QRect>::ConstIterator endIt = m_pos.constEnd(); + for(QMap<QCString,QRect>::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(), QPoint(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 + QWidget *w = titem->widget(); + parent->container()->deleteWidget(w); // delete the layout widget + FormManager::self()->windowChanged(m_form->widget()); // to reload ObjectTreeView +} + +QString +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()) + { + QRect 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(); +} + +QString +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(QDomDocument &domDoc, Container *container, const QPoint& 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; + + QRect boundingRect; + for(QDomNode n = domDoc.namedItem("UI").firstChild(); !n.isNull(); n = n.nextSibling()) // more than one widget + { + if(n.toElement().tagName() != "widget") + continue; + QDomElement el = n.toElement(); + + QDomElement rect; + for(QDomNode n = el.firstChild(); !n.isNull(); n = n.nextSibling()) + { + if((n.toElement().tagName() == "property") && (n.toElement().attribute("name") == "geometry")) + rect = n.firstChild().toElement(); + } + + QDomElement x = rect.namedItem("x").toElement(); + QDomElement y = rect.namedItem("y").toElement(); + QDomElement wi = rect.namedItem("width").toElement(); + QDomElement 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(); + QRect 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(); + QString errMsg; + int errLine; + int errCol; + QDomDocument 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 + { + QDomElement 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(QDomNode n = domDoc.namedItem("UI").firstChild(); !n.isNull(); n = n.nextSibling()) // more than one widget + { + if(n.toElement().tagName() != "widget") + continue; + QDomElement 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(QDomNode n = domDoc.namedItem("UI").firstChild(); !n.isNull(); n = n.nextSibling()) + { + if(n.toElement().tagName() != "widget") + continue; + for(QDomNode 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(); + QStringList::ConstIterator endIt = m_names.constEnd(); + for(QStringList::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 + QStringList::ConstIterator endIt = m_names.constEnd(); + for(QStringList::ConstIterator it = m_names.constBegin(); it != endIt; ++it) + { + ObjectTreeItem* titem = container->form()->objectTree()->lookup(*it); + if (!titem) + continue; //better this than a crash + QWidget *w = titem->widget(); + container->deleteWidget(w); + } +} + +QString +PasteWidgetCommand::name() const +{ + return i18n("Paste"); +} + +void +//QDomElement +PasteWidgetCommand::changePos(QDomElement &el, const QPoint &newpos) +{ + //QDomElement el = widg.cloneNode(true).toElement(); + QDomElement rect; + // Find the widget geometry if there is one + for(QDomNode n = el.firstChild(); !n.isNull(); n = n.nextSibling()) + { + if((n.toElement().tagName() == "property") && (n.toElement().attribute("name") == "geometry")) + rect = n.firstChild().toElement(); + } + + QDomElement x = rect.namedItem("x").toElement(); + x.removeChild(x.firstChild()); + QDomText valueX = el.ownerDocument().createTextNode(QString::number(newpos.x())); + x.appendChild(valueX); + + QDomElement y = rect.namedItem("y").toElement(); + y.removeChild(y.firstChild()); + QDomText valueY = el.ownerDocument().createTextNode(QString::number(newpos.y())); + y.appendChild(valueY); + + //return el; +} + +void +PasteWidgetCommand::fixPos(QDomElement &el, Container *container) +{ +/* QDomElement rect; + for(QDomNode n = el.firstChild(); !n.isNull(); n = n.nextSibling()) + { + if((n.toElement().tagName() == "property") && (n.toElement().attribute("name") == "geometry")) + rect = n.firstChild().toElement(); + } + + QDomElement x = rect.namedItem("x").toElement(); + QDomElement y = rect.namedItem("y").toElement(); + QDomElement wi = rect.namedItem("width").toElement(); + QDomElement 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(); + QRect r(rx, ry, rw, rh); + + QWidget *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 != QRect(rx, ry, rw, rh)) + //return el; + //else + changePos(el, QPoint(r.x(), r.y())); +*/ + moveWidgetBy(el, container, QPoint(0, 0)); +} + +void +PasteWidgetCommand::moveWidgetBy(QDomElement &el, Container *container, const QPoint &p) +{ + QDomElement rect; + for(QDomNode n = el.firstChild(); !n.isNull(); n = n.nextSibling()) + { + if((n.toElement().tagName() == "property") && (n.toElement().attribute("name") == "geometry")) + rect = n.firstChild().toElement(); + } + + QDomElement x = rect.namedItem("x").toElement(); + QDomElement y = rect.namedItem("y").toElement(); + QDomElement wi = rect.namedItem("width").toElement(); + QDomElement 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(); + QRect r(rx + p.x(), ry + p.y(), rw, rh); + kdDebug() << "Moving widget by " << p << " from " << rx << " " << ry << " to " << r.topLeft() << endl; + + QWidget *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 != QRect(rx, ry, rw, rh)) + //return el; + //else + changePos(el, QPoint(r.x(), r.y())); +} + +void +PasteWidgetCommand::fixNames(QDomElement &el) +{ + QString wname; + for(QDomNode 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) + QString::number(num+1); + else + wname += "2"; + } + if(wname != n.toElement().text()) // we change the name, so we recreate the element + { + n.removeChild(n.firstChild()); + QDomElement type = el.ownerDocument().createElement("string"); + QDomText valueE = el.ownerDocument().createTextNode(wname); + type.appendChild(valueE); + n.toElement().appendChild(type); + } + + } + if(n.toElement().tagName() == "widget") // fix child widgets names + { + QDomElement 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 = QDomDocument("UI"); + m_domDoc.appendChild(m_domDoc.createElement("UI")); + + QDomElement parent = m_domDoc.namedItem("UI").toElement(); + + //for(QWidget *w = list.first(); w; w = list.next()) + /*for(WidgetListIterator it(list); it.current() != 0; ++it) + { + QWidget *w = it.current(); + // Don't delete tabwidget or widgetstack pages + if(w->parentWidget()->inherits("QWidgetStack")) + { + 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; + + QMap<QCString,QCString>::ConstIterator endIt = m_containers.constEnd(); + for(QMap<QCString,QCString>::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() +{ + QCString wname; + m_form->setInteractiveMode(false); + for(QDomNode 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(QDomNode 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]); + QDomElement widg = n.toElement(); + if(parent) + FormIO::loadWidget(cont, widg, parent->widget()); + else + FormIO::loadWidget(cont, widg); + } + m_form->setInteractiveMode(true); +} + +QString +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); +} + +QString +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 QString & name ) + : KMacroCommand(name) + { + } + const QPtrList<KCommand>& commands() const { return m_commands; } +}; +} + +CommandGroup::CommandGroup( const QString & name, WidgetPropertySet *propSet ) + : Command() + , m_subCommands(new SubCommands(name)) + , m_propSet(propSet) +{ +} + +CommandGroup::~CommandGroup() +{ + delete m_subCommands; +} + +const QPtrList<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 (QPtrListIterator<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); +} + +QString 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 (QPtrListIterator<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; +} |