kexi

commands.cpp

00001 /* This file is part of the KDE project
00002    Copyright (C) 2004 Cedric Pasteur <cedric.pasteur@free.fr>
00003    Copyright (C) 2005 Jaroslaw Staniek <js@iidea.pl>
00004 
00005    This library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Library General Public
00007    License as published by the Free Software Foundation; either
00008    version 2 of the License, or (at your option) any later version.
00009 
00010    This library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Library General Public License for more details.
00014 
00015    You should have received a copy of the GNU Library General Public License
00016    along with this library; see the file COPYING.LIB.  If not, write to
00017    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018  * Boston, MA 02110-1301, USA.
00019 */
00020 #include <qdom.h>
00021 #include <qwidget.h>
00022 #include <qlayout.h>
00023 #include <qlabel.h>
00024 #include <qsplitter.h>
00025 #include <qmetaobject.h>
00026 
00027 #include <kdebug.h>
00028 #include <klocale.h>
00029 #include <kpopupmenu.h>
00030 #include <kmessagebox.h>
00031 #include <kaccelmanager.h>
00032 
00033 #include "formIO.h"
00034 #include "container.h"
00035 #include "objecttree.h"
00036 #include "formmanager.h"
00037 #include "form.h"
00038 #include "widgetlibrary.h"
00039 #include "events.h"
00040 #include "utils.h"
00041 #include "widgetpropertyset.h"
00042 #include "widgetwithsubpropertiesinterface.h"
00043 #include <koproperty/property.h>
00044 
00045 #include "commands.h"
00046 
00047 using namespace KFormDesigner;
00048 
00049 // Command
00050 
00051 Command::Command()
00052  : KCommand()
00053 {
00054 }
00055 
00056 Command::~Command()
00057 {
00058 }
00059 
00060 // PropertyCommand
00061 
00062 PropertyCommand::PropertyCommand(WidgetPropertySet *set, const QCString &wname,
00063     const QVariant &oldValue, const QVariant &value, const QCString &property)
00064   : Command(), m_propSet(set), m_value(value), m_property(property)
00065 {
00066     m_oldvalues.insert(wname, oldValue);
00067 }
00068 
00069 PropertyCommand::PropertyCommand(WidgetPropertySet *set, const QMap<QCString, QVariant> &oldvalues,
00070     const QVariant &value, const QCString &property)
00071   : Command(), m_propSet(set), m_value(value), m_oldvalues(oldvalues), m_property(property)
00072 {
00073 }
00074 
00075 /*
00076 MultiCommand::MultiCommand()
00077 {
00078 }
00079 
00080 MultiCommandGroup::addSubCommand(PropertyCommand* subCommand)
00081   : Command(), m_propSet(set), m_value(value), m_oldvalues(oldvalues), m_property(property)
00082 {
00083 }
00084 */
00085 
00086 void
00087 PropertyCommand::setValue(const QVariant &value)
00088 {
00089     m_value = value;
00090     emit FormManager::self()->dirty(FormManager::self()->activeForm());
00091 }
00092 
00093 void
00094 PropertyCommand::execute()
00095 {
00096     FormManager::self()->activeForm()->selectFormWidget();
00097     m_propSet->setUndoing(true);
00098 
00099     QMap<QCString, QVariant>::ConstIterator endIt = m_oldvalues.constEnd();
00100     for(QMap<QCString, QVariant>::ConstIterator it = m_oldvalues.constBegin(); it != endIt; ++it)
00101     {
00102         ObjectTreeItem* item = FormManager::self()->activeForm()->objectTree()->lookup(it.key());
00103         if (item) {//we're checking for item!=0 because the name could be of a form widget
00104             FormManager::self()->activeForm()->setSelectedWidget(item->widget(), true);
00105         }
00106     }
00107 
00108     (*m_propSet)[m_property] = m_value;
00109     m_propSet->setUndoing(false);
00110 }
00111 
00112 void
00113 PropertyCommand::unexecute()
00114 {
00115     FormManager::self()->activeForm()->selectFormWidget();
00116     m_propSet->setUndoing(true);
00117 
00118     QMap<QCString, QVariant>::ConstIterator endIt = m_oldvalues.constEnd();
00119     for(QMap<QCString, QVariant>::ConstIterator it = m_oldvalues.constBegin(); it != endIt; ++it)
00120     {
00121         ObjectTreeItem* item = FormManager::self()->activeForm()->objectTree()->lookup(it.key());
00122         if (!item)
00123             continue; //better this than a crash
00124         QWidget *widg = item->widget();
00125         FormManager::self()->activeForm()->setSelectedWidget(widg, true);
00126         //m_propSet->setSelectedWidget(widg, true);
00127 
00128         WidgetWithSubpropertiesInterface* subpropIface = dynamic_cast<WidgetWithSubpropertiesInterface*>(widg);
00129         QWidget *subWidget = (subpropIface && subpropIface->subwidget()) ? subpropIface->subwidget() : widg;
00130         if (-1!=subWidget->metaObject()->findProperty( m_property, true ))
00131             subWidget->setProperty(m_property, it.data());
00132     }
00133 
00134     (*m_propSet)[m_property] = m_oldvalues.begin().data();
00135     m_propSet->setUndoing(false);
00136 }
00137 
00138 QString
00139 PropertyCommand::name() const
00140 {
00141     if(m_oldvalues.count() >= 2)
00142         return i18n("Change \"%1\" property for multiple widgets" ).arg(m_property);
00143     else
00144         return i18n("Change \"%1\" property for widget \"%2\"" ).arg(m_property).arg(m_oldvalues.begin().key());
00145 }
00146 
00147 void
00148 PropertyCommand::debug()
00149 {
00150     kdDebug() << "PropertyCommand: name=\"" << name() << "\" widgets=" << m_oldvalues.keys() 
00151         << " value=" << m_value << " oldValues=" << m_oldvalues.values() << endl;
00152 }
00153 
00154 // GeometryPropertyCommand (for multiples widgets)
00155 
00156 GeometryPropertyCommand::GeometryPropertyCommand(WidgetPropertySet *set, 
00157     const QStringList &names, const QPoint& oldPos)
00158  : Command(), m_propSet(set), m_names(names), m_oldPos(oldPos)
00159 {
00160 }
00161 
00162 void
00163 GeometryPropertyCommand::execute()
00164 {
00165     m_propSet->setUndoing(true);
00166     int dx = m_pos.x() - m_oldPos.x();
00167     int dy = m_pos.y() - m_oldPos.y();
00168 
00169     QStringList::ConstIterator endIt = m_names.constEnd();
00170     // We move every widget in our list by (dx, dy)
00171     for(QStringList::ConstIterator it = m_names.constBegin(); it != endIt; ++it)
00172     {
00173         ObjectTreeItem* item = FormManager::self()->activeForm()->objectTree()->lookup(*it);
00174         if (!item)
00175             continue; //better this than a crash
00176         QWidget *w = item->widget();
00177         w->move(w->x() + dx, w->y() + dy);
00178     }
00179     m_propSet->setUndoing(false);
00180 }
00181 
00182 void
00183 GeometryPropertyCommand::unexecute()
00184 {
00185     m_propSet->setUndoing(true);
00186     int dx = m_pos.x() - m_oldPos.x();
00187     int dy = m_pos.y() - m_oldPos.y();
00188 
00189     QStringList::ConstIterator endIt = m_names.constEnd();
00190     // We move every widget in our list by (-dx, -dy) to undo the move
00191     for(QStringList::ConstIterator it = m_names.constBegin(); it != endIt; ++it)
00192     {
00193         ObjectTreeItem* item = FormManager::self()->activeForm()->objectTree()->lookup(*it);
00194         if (!item)
00195             continue; //better this than a crash
00196         QWidget *w = item->widget();
00197         w->move(w->x() - dx, w->y() - dy);
00198     }
00199     m_propSet->setUndoing(false);
00200 }
00201 
00202 void
00203 GeometryPropertyCommand::setPos(const QPoint& pos)
00204 {
00205     m_pos = pos;
00206     emit FormManager::self()->dirty(FormManager::self()->activeForm());
00207 }
00208 
00209 QString
00210 GeometryPropertyCommand::name() const
00211 {
00212     return i18n("Move multiple widgets");
00213 }
00214 
00215 void
00216 GeometryPropertyCommand::debug()
00217 {
00218     kdDebug() << "GeometryPropertyCommand: pos=" << m_pos << " oldPos=" << m_oldPos 
00219         << " widgets=" << m_names << endl;
00220 }
00221 
00223 
00224 AlignWidgetsCommand::AlignWidgetsCommand(int type, WidgetList &list, Form *form)
00225 : Command(), m_form(form), m_type(type)
00226 {
00227     for(QWidget *w = list.first(); w; w = list.next())
00228         m_pos.insert(w->name(), w->pos());
00229 }
00230 
00231 void
00232 AlignWidgetsCommand::execute()
00233 {
00234     // To avoid creation of GeometryPropertyCommand
00235     m_form->selectFormWidget();
00236 
00237     int gridX = m_form->gridSize();
00238     int gridY = m_form->gridSize();
00239     QWidget *parentWidget = m_form->selectedWidgets()->first()->parentWidget();
00240     int tmpx, tmpy;
00241 
00242     WidgetList list;
00243     QMap<QCString, QPoint>::ConstIterator endIt = m_pos.constEnd();
00244     for(QMap<QCString, QPoint>::ConstIterator it = m_pos.constBegin(); it != endIt; ++it)
00245     {
00246         ObjectTreeItem *item = m_form->objectTree()->lookup(it.key());
00247         if(item && item->widget())
00248             list.append(item->widget());
00249     }
00250 
00251     switch(m_type)
00252     {
00253         case AlignToGrid:
00254         {
00255             for(QWidget *w = list.first(); w; w = list.next())
00256             {
00257                 tmpx = int( (float)w->x() / ((float)gridX) + 0.5 ) * gridX;
00258                 tmpy = int( (float)w->y() / ((float)gridY) + 0.5 ) * gridY;
00259 
00260                 if((tmpx != w->x()) || (tmpy != w->y()))
00261                     w->move(tmpx, tmpy);
00262             }
00263             break;
00264         }
00265 
00266         case AlignToLeft:
00267         {
00268             tmpx = parentWidget->width();
00269             for(QWidget *w = list.first(); w; w = list.next())
00270             {
00271                 if(w->x() < tmpx)
00272                     tmpx = w->x();
00273             }
00274 
00275             for(QWidget *w = list.first(); w; w = list.next())
00276                 w->move(tmpx, w->y());
00277             break;
00278         }
00279 
00280         case AlignToRight:
00281         {
00282             tmpx = 0;
00283             for(QWidget *w = list.first(); w; w = list.next())
00284             {
00285                 if(w->x() + w->width() > tmpx)
00286                     tmpx = w->x() + w->width();
00287             }
00288 
00289             for(QWidget *w = list.first(); w; w = list.next())
00290                 w->move(tmpx - w->width(), w->y());
00291             break;
00292         }
00293 
00294         case AlignToTop:
00295         {
00296             tmpy = parentWidget->height();
00297             for(QWidget *w = list.first(); w; w = list.next())
00298             {
00299                 if(w->y() < tmpy)
00300                     tmpy = w->y();
00301             }
00302 
00303             for(QWidget *w = list.first(); w; w = list.next())
00304                 w->move(w->x(), tmpy);
00305             break;
00306         }
00307 
00308         case AlignToBottom:
00309         {
00310             tmpy = 0;
00311             for(QWidget *w = list.first(); w; w = list.next())
00312             {
00313                 if(w->y() + w->height() > tmpy)
00314                     tmpy = w->y() + w->height();
00315             }
00316 
00317             for(QWidget *w = list.first(); w; w = list.next())
00318                 w->move(w->x(), tmpy - w->height());
00319             break;
00320         }
00321 
00322         default:
00323             return;
00324     }
00325 
00326     // We restore selection
00327     for(QWidget *w = list.first(); w; w = list.next())
00328         m_form->setSelectedWidget(w, true);
00329 }
00330 
00331 void
00332 AlignWidgetsCommand::unexecute()
00333 {
00334     // To avoid creation of GeometryPropertyCommand
00335     m_form->selectFormWidget();
00336     // We move widgets to their original pos
00337     QMap<QCString, QPoint>::ConstIterator endIt = m_pos.constEnd();
00338     for(QMap<QCString, QPoint>::ConstIterator it = m_pos.constBegin(); it != endIt; ++it)
00339     {
00340         ObjectTreeItem *item = m_form->objectTree()->lookup(it.key());
00341         if(item && item->widget())
00342             item->widget()->move( m_pos[item->widget()->name()] );
00343         m_form->setSelectedWidget(item->widget(), true); // We restore selection
00344     }
00345 }
00346 
00347 QString
00348 AlignWidgetsCommand::name() const
00349 {
00350     switch(m_type)
00351     {
00352         case AlignToGrid:
00353             return i18n("Align Widgets to Grid");
00354         case AlignToLeft:
00355             return i18n("Align Widgets to Left");
00356         case AlignToRight:
00357             return i18n("Align Widgets to Right");
00358         case AlignToTop:
00359             return i18n("Align Widgets to Top");
00360         case AlignToBottom:
00361             return i18n("Align Widgets to Bottom");
00362         default:
00363             return QString::null;
00364     }
00365 }
00366 
00367 void
00368 AlignWidgetsCommand::debug()
00369 {
00370     kdDebug() << "AlignWidgetsCommand: name=\"" << name() << "\" form=" << m_form->widget()->name() 
00371         << " widgets=" << m_pos.keys() << endl;
00372 }
00373 
00375 
00376 AdjustSizeCommand::AdjustSizeCommand(int type, WidgetList &list, Form *form)
00377 : Command(), m_form(form), m_type(type)
00378 {
00379     for(QWidget *w = list.first(); w; w = list.next())
00380     {
00381         if(w->parentWidget() && w->parentWidget()->isA("QWidgetStack"))
00382         {
00383             w = w->parentWidget(); // widget is WidgetStack page
00384             if(w->parentWidget() && w->parentWidget()->inherits("QTabWidget")) // widget is tabwidget page
00385                 w = w->parentWidget();
00386         }
00387 
00388         m_sizes.insert(w->name(), w->size());
00389         if(m_type == SizeToGrid) // SizeToGrid also move widgets
00390             m_pos.insert(w->name(), w->pos());
00391     }
00392 }
00393 
00394 void
00395 AdjustSizeCommand::execute()
00396 {
00397     // To avoid creation of GeometryPropertyCommand
00398     m_form->selectFormWidget();
00399 
00400     int gridX = m_form->gridSize();
00401     int gridY = m_form->gridSize();
00402     int tmpw=0, tmph=0;
00403 
00404     WidgetList list;
00405     QMap<QCString, QSize>::ConstIterator endIt = m_sizes.constEnd();
00406     for(QMap<QCString, QSize>::ConstIterator it = m_sizes.constBegin(); it != endIt; ++it)
00407     {
00408         ObjectTreeItem *item = m_form->objectTree()->lookup(it.key());
00409         if(item && item->widget())
00410             list.append(item->widget());
00411     }
00412 
00413     switch(m_type)
00414     {
00415         case SizeToGrid:
00416         {
00417             int tmpx=0, tmpy=0;
00418             // same as in 'Align to Grid' + for the size
00419             for(QWidget *w = list.first(); w; w = list.next())
00420             {
00421                 tmpx = int( (float)w->x() / ((float)gridX) + 0.5 ) * gridX;
00422                 tmpy = int( (float)w->y() / ((float)gridY) + 0.5 ) * gridY;
00423                 tmpw = int( (float)w->width() / ((float)gridX) + 0.5 ) * gridX;
00424                 tmph = int( (float)w->height() / ((float)gridY) + 0.5 ) * gridY;
00425 
00426                 if((tmpx != w->x()) || (tmpy != w->y()))
00427                     w->move(tmpx, tmpy);
00428                 if((tmpw != w->width()) || (tmph != w->height()))
00429                     w->resize(tmpw, tmph);
00430             }
00431             break;
00432         }
00433 
00434         case SizeToFit:
00435         {
00436             for(QWidget *w = list.first(); w; w = list.next()) {
00437                 ObjectTreeItem *item = m_form->objectTree()->lookup(w->name());
00438                 if(item && !item->children()->isEmpty()) { // container
00439                     QSize s;
00440                     if(item->container() && item->container()->layout())
00441                         s = w->sizeHint();
00442                     else
00443                         s = getSizeFromChildren(item);
00444                     // minimum size for containers
00445                     if(s.width()  <  30)
00446                         s.setWidth(30);
00447                     if(s.height() < 30)
00448                         s.setHeight(30);
00449                     // small hack for flow layouts
00450                     int type = item->container() ? item->container()->layoutType() : Container::NoLayout;
00451                     if(type == Container::HFlow)
00452                         s.setWidth(s.width() + 5);
00453                     else if(type == Container::VFlow)
00454                         s.setHeight(s.height() + 5);
00455                     w->resize(s);
00456                 }
00457                 else if(item && item->container()) // empty container
00458                     w->resize(item->container()->form()->gridSize() * 5, item->container()->form()->gridSize() * 5); // basic size
00459                 else {
00460                     QSize sizeHint(w->sizeHint());
00461                     if (sizeHint.isValid())
00462                         w->resize(sizeHint);
00463                 }
00464             }
00465             break;
00466         }
00467 
00468         case SizeToSmallWidth:
00469         {
00470             for(QWidget *w = list.first(); w; w = list.next())
00471             {
00472                 if((tmpw == 0) || (w->width() < tmpw))
00473                     tmpw = w->width();
00474             }
00475 
00476             for(QWidget *w = list.first(); w; w = list.next())
00477             {
00478                 if(tmpw != w->width())
00479                     w->resize(tmpw, w->height());
00480             }
00481             break;
00482         }
00483 
00484         case SizeToBigWidth:
00485         {
00486             for(QWidget *w = list.first(); w; w = list.next())
00487             {
00488                 if(w->width() > tmpw)
00489                     tmpw = w->width();
00490             }
00491 
00492             for(QWidget *w = list.first(); w; w = list.next())
00493             {
00494                 if(tmpw != w->width())
00495                     w->resize(tmpw, w->height());
00496             }
00497             break;
00498         }
00499 
00500         case SizeToSmallHeight:
00501         {
00502             for(QWidget *w = list.first(); w; w = list.next())
00503             {
00504                 if((tmph == 0) || (w->height() < tmph))
00505                     tmph = w->height();
00506             }
00507 
00508             for(QWidget *w = list.first(); w; w = list.next())
00509             {
00510                 if(tmph != w->height())
00511                     w->resize(w->width(), tmph);
00512             }
00513             break;
00514         }
00515 
00516         case SizeToBigHeight:
00517         {
00518             for(QWidget *w = list.first(); w; w = list.next())
00519             {
00520                 if(w->height() > tmph)
00521                     tmph = w->height();
00522             }
00523 
00524             for(QWidget *w = list.first(); w; w = list.next())
00525             {
00526                 if(tmph != w->height())
00527                     w->resize(w->width(), tmph);
00528             }
00529             break;
00530         }
00531 
00532         default:
00533             break;
00534     }
00535 
00536     // We restore selection
00537     for(QWidget *w = list.first(); w; w = list.next())
00538         m_form->setSelectedWidget(w, true);
00539 }
00540 
00541 QSize
00542 AdjustSizeCommand::getSizeFromChildren(ObjectTreeItem *item)
00543 {
00544     if(!item->container()) // multi pages containers (eg tabwidget)
00545     {
00546         QSize s;
00547         // get size for each container, and keep the biggest one
00548         for(ObjectTreeItem *tree = item->children()->first(); tree; tree = item->children()->next())
00549             s = s.expandedTo(getSizeFromChildren(tree));
00550         return s;
00551     }
00552 
00553     int tmpw = 0, tmph = 0;
00554     for(ObjectTreeItem *tree = item->children()->first(); tree; tree = item->children()->next()) {
00555         if(!tree->widget())
00556             continue;
00557         tmpw = QMAX(tmpw, tree->widget()->geometry().right());
00558         tmph = QMAX(tmph, tree->widget()->geometry().bottom());
00559     }
00560 
00561     return QSize(tmpw, tmph) + QSize(10, 10);
00562 }
00563 
00564 void
00565 AdjustSizeCommand::unexecute()
00566 {
00567     // To avoid creation of GeometryPropertyCommand
00568     m_form->selectFormWidget();
00569     // We resize widgets to their original size
00570     QMap<QCString, QSize>::ConstIterator endIt = m_sizes.constEnd();
00571     for(QMap<QCString, QSize>::ConstIterator it = m_sizes.constBegin(); it != endIt; ++it)
00572     {
00573         ObjectTreeItem *item = m_form->objectTree()->lookup(it.key());
00574         if(item && item->widget())
00575         {
00576             item->widget()->resize(  m_sizes[item->widget()->name()] );
00577             if(m_type == SizeToGrid)
00578                 item->widget()->move( m_pos[item->widget()->name()] );
00579             m_form->setSelectedWidget(item->widget(), true); // We restore selection
00580         }
00581     }
00582 }
00583 
00584 QString
00585 AdjustSizeCommand::name() const
00586 {
00587     switch(m_type)
00588     {
00589         case SizeToGrid:
00590             return i18n("Resize Widgets to Grid");
00591         case SizeToFit:
00592             return i18n("Resize Widgets to Fit Contents");
00593         case SizeToSmallWidth:
00594             return i18n("Resize Widgets to Narrowest");
00595         case SizeToBigWidth:
00596             return i18n("Resize Widgets to Widest");
00597         case SizeToSmallHeight:
00598             return i18n("Resize Widgets to Shortest");
00599         case SizeToBigHeight:
00600             return i18n("Resize Widgets to Tallest");
00601         default:
00602             return QString::null;
00603     }
00604 }
00605 
00606 void
00607 AdjustSizeCommand::debug()
00608 {
00609     kdDebug() << "AdjustSizeCommand: name=\"" << name() << "\" form=" << m_form->widget()->name() 
00610         << " widgets=" << m_sizes.keys() << endl;
00611 }
00612 
00613 // LayoutPropertyCommand
00614 
00615 LayoutPropertyCommand::LayoutPropertyCommand(WidgetPropertySet *buf, const QCString &wname, 
00616     const QVariant &oldValue, const QVariant &value)
00617  : PropertyCommand(buf, wname, oldValue, value, "layout")
00618 {
00619     m_form = FormManager::self()->activeForm();
00620     ObjectTreeItem* titem = m_form->objectTree()->lookup(wname);
00621     if (!titem)
00622         return; //better this than a crash
00623     Container *m_container = titem->container();
00624     // We save the geometry of each wigdet
00625     for(ObjectTreeItem *it = m_container->objectTree()->children()->first(); it; it = m_container->objectTree()->children()->next())
00626         m_geometries.insert(it->name().latin1(), it->widget()->geometry());
00627 }
00628 
00629 void
00630 LayoutPropertyCommand::execute()
00631 {
00632     PropertyCommand::execute();
00633 }
00634 
00635 void
00636 LayoutPropertyCommand::unexecute()
00637 {
00638     ObjectTreeItem* titem = m_form->objectTree()->lookup(m_oldvalues.begin().key());
00639     if (!titem)
00640         return; //better this than a crash
00641     Container *m_container = titem->container();
00642     m_container->setLayout(Container::NoLayout);
00643     // We put every widget back in its old location
00644     QMap<QCString,QRect>::ConstIterator endIt = m_geometries.constEnd();
00645     for(QMap<QCString,QRect>::ConstIterator it = m_geometries.constBegin(); it != endIt; ++it)
00646     {
00647         ObjectTreeItem *tree = m_container->form()->objectTree()->lookup(it.key());
00648         if(tree)
00649             tree->widget()->setGeometry(it.data());
00650     }
00651 
00652     PropertyCommand::unexecute();
00653 }
00654 
00655 QString
00656 LayoutPropertyCommand::name() const
00657 {
00658     return i18n("Change layout of widget \"%1\"").arg(m_oldvalues.begin().key());
00659 }
00660 
00661 void
00662 LayoutPropertyCommand::debug()
00663 {
00664     kdDebug() << "LayoutPropertyCommand: name=\"" << name() << "\" oldValue=" << m_oldvalues.keys()
00665         << " value=" << m_value << endl;
00666 }
00667 
00668 // InsertWidgetCommand
00669 
00670 InsertWidgetCommand::InsertWidgetCommand(Container *container)
00671   : Command()
00672 {
00673     m_containername = container->widget()->name();
00674     m_form = container->form();
00675     m_class = FormManager::self()->selectedClass();
00676     m_insertRect = container->m_insertRect;
00677     m_point = container->m_insertBegin;
00678     m_name = container->form()->objectTree()->generateUniqueName(
00679         container->form()->library()->namePrefix(m_class).latin1(),false);
00681 }
00682 
00683 InsertWidgetCommand::InsertWidgetCommand(Container *container,
00684     const QCString& className, const QPoint& pos, const QCString& namePrefix)
00685   : Command()
00686 {
00687     m_containername = container->widget()->name();
00688     m_form = container->form();
00689     m_class = className;
00690     //m_insertRect is null (default)
00691     m_point = pos;
00692     if (namePrefix.isEmpty()) {
00693         m_name = container->form()->objectTree()->generateUniqueName(
00694             container->form()->library()->namePrefix(m_class).latin1() );
00695     }
00696     else {
00697         m_name = container->form()->objectTree()->generateUniqueName(
00698             namePrefix, false  );
00699     }
00700 }
00701 
00702 void
00703 InsertWidgetCommand::execute()
00704 {
00705     if (!m_form->objectTree())
00706         return;
00707     ObjectTreeItem* titem = m_form->objectTree()->lookup(m_containername);
00708     if (!titem)
00709         return; //better this than a crash
00710     Container *m_container = titem->container();
00711     int options = WidgetFactory::DesignViewMode | WidgetFactory::AnyOrientation;
00712     if (m_container->form()->library()->internalProperty(m_class, "orientationSelectionPopup")=="1") {
00713         if(m_insertRect.isValid()) {
00714             if (m_insertRect.width() < m_insertRect.height()) {
00715                 options |= WidgetFactory::VerticalOrientation;
00716                 options ^= WidgetFactory::AnyOrientation;
00717             }
00718             else if (m_insertRect.width() > m_insertRect.height()) {
00719                 options |= WidgetFactory::HorizontalOrientation;
00720                 options ^= WidgetFactory::AnyOrientation;
00721             }
00722         }
00723         if (options & WidgetFactory::AnyOrientation) {
00724             options ^= WidgetFactory::AnyOrientation;
00725             options |= m_container->form()->library()->showOrientationSelectionPopup(
00726                 m_class, m_container->m_container,
00727                 m_container->form()->widget()->mapToGlobal(m_point));
00728             if (options & WidgetFactory::AnyOrientation)
00729                 return; //cancelled
00730         }
00731     }
00732     else
00733         options |= WidgetFactory::AnyOrientation;
00734 
00735     QWidget *w = m_container->form()->library()->createWidget(m_class, m_container->m_container, m_name,
00736         m_container, options);
00737 
00738     if(!w) {
00739         FormManager::self()->stopInsert();
00740         WidgetInfo *winfo = m_container->form()->library()->widgetInfoForClassName(m_class);
00741         KMessageBox::sorry(FormManager::self()->activeForm() ? FormManager::self()->activeForm()->widget() : 0,
00742                 i18n("Could not insert widget of type \"%1\". A problem with widget's creation encountered.")
00743                 .arg(winfo ? winfo->name() : QString::null));
00744         kdWarning() << "InsertWidgetCommand::execute() ERROR: widget creation failed" << endl;
00745         return;
00746     }
00747 #if KDE_VERSION >= KDE_MAKE_VERSION(3,4,0) 
00749     if (m_form->designMode()) {
00750         //don't generate accelerators for widgets in design mode
00751         KAcceleratorManager::setNoAccel(w);
00752     }
00753 #endif
00754 
00755     // if the insertRect is invalid (ie only one point), we use widget' size hint
00756     if(( (m_insertRect.width() < 21) && (m_insertRect.height() < 21)))
00757     {
00758         QSize s = w->sizeHint();
00759 
00760         if(s.isEmpty())
00761             s = QSize(20, 20); // Minimum size to avoid creating a (0,0) widget
00762         int x, y;
00763         if(m_insertRect.isValid())
00764         {
00765             x = m_insertRect.x();
00766             y = m_insertRect.y();
00767         }
00768         else
00769         {
00770             x = m_point.x();
00771             y = m_point.y();
00772         }
00773         m_insertRect = QRect(x, y, s.width() + 16/* add some space so more text can be entered*/,
00774             s.height());
00775     }
00776     w->move(m_insertRect.x(), m_insertRect.y());
00777     w->resize(m_insertRect.width()-1, m_insertRect.height()-1); // -1 is not to hide dots
00778     w->setStyle(&(m_container->widget()->style()));
00779     w->setBackgroundOrigin(QWidget::ParentOrigin);
00780     w->show();
00781 
00782     FormManager::self()->stopInsert();
00783 
00784     // ObjectTreeItem object already exists for widgets which corresponds to a Container
00785     // it's already created in Container's constructor
00786     ObjectTreeItem *item = m_container->form()->objectTree()->lookup(m_name);
00787     if (!item) { //not yet created...
00788         m_container->form()->objectTree()->addItem(m_container->m_tree,
00789             item = new ObjectTreeItem(m_container->form()->library()->displayName(m_class), m_name, w, m_container)
00790         );
00791     }
00792     //assign item for its widget if it supports DesignTimeDynamicChildWidgetHandler interface
00793     //(e.g. KexiDBAutoField)
00794     if (m_form->designMode() && dynamic_cast<DesignTimeDynamicChildWidgetHandler*>(w)) {
00795         dynamic_cast<DesignTimeDynamicChildWidgetHandler*>(w)->assignItem(item);
00796     }
00797 
00798     // We add the autoSaveProperties in the modifProp list of the ObjectTreeItem, so that they are saved later
00799     QValueList<QCString> list(m_container->form()->library()->autoSaveProperties(w->className()));
00800 
00801     QValueList<QCString>::ConstIterator endIt = list.constEnd();
00802     for(QValueList<QCString>::ConstIterator it = list.constBegin(); it != endIt; ++it)
00803         item->addModifiedProperty(*it, w->property(*it));
00804 
00805     m_container->reloadLayout(); // reload the layout to take the new wigdet into account
00806 
00807     m_container->setSelectedWidget(w, false);
00808     if (m_container->form()->library()->internalProperty(w->className(), 
00809             "dontStartEditingOnInserting").isEmpty())
00810     {
00811         m_container->form()->library()->startEditing(
00812             w->className(), w, item->container() ? item->container() : m_container); // we edit the widget on creation
00813     }
00815     kdDebug() << "Container::eventFilter(): widget added " << this << endl;
00816 }
00817 
00818 void
00819 InsertWidgetCommand::unexecute()
00820 {
00821     ObjectTreeItem* titem = m_form->objectTree()->lookup(m_name);
00822     if (!titem)
00823         return; //better this than a crash
00824     QWidget *m_widget = titem->widget();
00825     Container *m_container = m_form->objectTree()->lookup(m_containername)->container();
00826     m_container->deleteWidget(m_widget);
00827 }
00828 
00829 QString
00830 InsertWidgetCommand::name() const
00831 {
00832     if(!m_name.isEmpty())
00833         return i18n("Insert widget \"%1\"").arg(m_name);
00834     else
00835         return i18n("Insert widget");
00836 }
00837 
00838 void
00839 InsertWidgetCommand::debug()
00840 {
00841     kdDebug() << "InsertWidgetCommand: name=\"" << name() << "\" generatedName=" << m_name 
00842         << " container=" << m_containername
00843         << " form=" << m_form->widget()->name() << " class=" << m_class 
00844         << " rect=" << m_insertRect << " pos=" << m_point << endl;
00845 }
00846 
00848 
00849 CreateLayoutCommand::CreateLayoutCommand(int layoutType, WidgetList &list, Form *form)
00850  : m_form(form), m_type(layoutType)
00851 {
00852     WidgetList *m_list=0;
00853     switch(layoutType)
00854     {
00855         case Container::HBox:
00856         case Container::Grid:
00857         case Container::HSplitter:
00858         case Container::HFlow:
00859             m_list = new HorWidgetList(form->toplevelContainer()->widget()); break;
00860         case Container::VBox:
00861         case Container::VSplitter:
00862         case Container::VFlow:
00863             m_list = new VerWidgetList(form->toplevelContainer()->widget()); break;
00864     }
00865     for(QWidget *w = list.first(); w; w = list.next())
00866         m_list->append(w);
00867     m_list->sort(); // we sort them now, before creating the layout
00868 
00869     for(QWidget *w = m_list->first(); w; w = m_list->next())
00870         m_pos.insert(w->name(), w->geometry());
00871     ObjectTreeItem *item = form->objectTree()->lookup(m_list->first()->name());
00872     if(item && item->parent()->container())
00873         m_containername = item->parent()->name();
00874     delete m_list;
00875 }
00876 
00877 void
00878 CreateLayoutCommand::execute()
00879 {
00880     WidgetLibrary *lib = m_form->library();
00881     if(!lib)
00882         return;
00883     ObjectTreeItem* titem = m_form->objectTree()->lookup(m_containername);
00884     Container *container = titem ? titem->container() : 0;
00885     if(!container)
00886         container = m_form->toplevelContainer(); // use toplevelContainer by default
00887 
00888     QCString classname;
00889     switch(m_type)  {
00890         case Container::HSplitter: case Container::VSplitter:
00891             classname = "QSplitter"; break;
00892         default:
00893             classname = Container::layoutTypeToString(m_type).latin1();
00894     }
00895 
00896     if(m_name.isEmpty())// the name must be generated only once
00897         m_name = m_form->objectTree()->generateUniqueName(classname);
00898 
00899     QWidget *w = lib->createWidget(classname, container->widget(), m_name.latin1(), container);
00900 #if KDE_VERSION >= KDE_MAKE_VERSION(3,4,0) 
00902     if (w) {
00903         if (m_form->designMode()) {
00904             //don't generate accelerators for widgets in design mode
00905             KAcceleratorManager::setNoAccel(w);
00906         }
00907     }
00908 #endif
00909     ObjectTreeItem *tree = w ? m_form->objectTree()->lookup(w->name()) : 0;
00910     if(!tree)
00911         return;
00912 
00913     container->setSelectedWidget(0, false);
00914     w->move(m_pos.begin().data().topLeft()); // we move the layout at the position of the topleft widget
00915     // sizeHint of these widgets depends on geometry, so give them appropriate geometry
00916     if(m_type == Container::HFlow)
00917         w->resize( QSize(700, 20) );
00918     else if(m_type == Container::VFlow)
00919         w->resize( QSize(20, 700));
00920     w->show();
00921 
00922     // We reparent every widget to the Layout and insert them into it
00923     QMap<QCString,QRect>::ConstIterator endIt = m_pos.constEnd();
00924     for(QMap<QCString,QRect>::ConstIterator it = m_pos.constBegin(); it != endIt; ++it)
00925     {
00926         ObjectTreeItem *item = m_form->objectTree()->lookup(it.key());
00927         if(item && item->widget())
00928         {
00929             item->widget()->reparent(w, item->widget()->pos(), true);
00930             item->eventEater()->setContainer(tree->container());
00931             m_form->objectTree()->reparent(item->name(), m_name);
00932         }
00933     }
00934 
00935     if(m_type == Container::HSplitter)
00936         ((QSplitter*)w)->setOrientation(QSplitter::Horizontal);
00937     else if(m_type == Container::VSplitter)
00938         ((QSplitter*)w)->setOrientation(QSplitter::Vertical);
00939     else if(tree->container()) {
00940         tree->container()->setLayout((Container::LayoutType)m_type);
00941         w->resize(tree->container()->layout()->sizeHint()); // the layout doesn't have its own size
00942     }
00943 
00944     container->setSelectedWidget(w, false);
00945     FormManager::self()->windowChanged(m_form->widget()); // to reload the ObjectTreeView
00946 }
00947 
00948 void
00949 CreateLayoutCommand::unexecute()
00950 {
00951     ObjectTreeItem *parent = m_form->objectTree()->lookup(m_containername);
00952     if(!parent)
00953         parent = m_form->objectTree();
00954 
00955     // We reparent every widget to the Container and take them out of the layout
00956     QMap<QCString,QRect>::ConstIterator endIt = m_pos.constEnd();
00957     for(QMap<QCString,QRect>::ConstIterator it = m_pos.constBegin(); it != endIt; ++it)
00958     {
00959         ObjectTreeItem *item = m_form->objectTree()->lookup(it.key());
00960         if(item && item->widget())
00961         {
00962             item->widget()->reparent(parent->widget(), QPoint(0,0), true);
00963             item->eventEater()->setContainer(parent->container());
00964             if(m_pos[it.key()].isValid())
00965                 item->widget()->setGeometry(m_pos[it.key()]);
00966             m_form->objectTree()->reparent(item->name(), m_containername);
00967         }
00968     }
00969 
00970     if(!parent->container())
00971         return;
00972     ObjectTreeItem* titem = m_form->objectTree()->lookup(m_name);
00973     if (!titem)
00974         return; //better this than a crash
00975     QWidget *w = titem->widget();
00976     parent->container()->deleteWidget(w); // delete the layout widget
00977     FormManager::self()->windowChanged(m_form->widget()); // to reload ObjectTreeView
00978 }
00979 
00980 QString
00981 CreateLayoutCommand::name() const
00982 {
00983     switch(m_type)
00984     {
00985         case Container::HBox:
00986             return i18n("Group Widgets Horizontally");
00987         case Container::VBox:
00988             return i18n("Group Widgets Vertically");
00989         case Container::Grid:
00990             return i18n("Group Widgets in a Grid");
00991         case Container::HSplitter:
00992             return i18n("Group Widgets Horizontally in a Splitter");
00993         case Container::VSplitter:
00994             return i18n("Group Widgets Vertically in a Splitter");
00995         case Container::HFlow:
00996             return i18n("Group Widgets By Rows");
00997         case Container::VFlow:
00998             return i18n("Group Widgets Vertically By Columns");
00999         default:
01000             return i18n("Group widgets");
01001     }
01002 }
01003 
01004 void
01005 CreateLayoutCommand::debug()
01006 {
01007     kdDebug() << "CreateLayoutCommand: name=\"" << name() << "\" generatedName=" << m_name 
01008         << " widgets=" << m_pos.keys() << " container=" << m_containername
01009         << " form=" << m_form->widget()->name() << endl;
01010 }
01011 
01013 
01014 BreakLayoutCommand::BreakLayoutCommand(Container *container)
01015  : CreateLayoutCommand()
01016 {
01017     m_containername = container->toplevel()->widget()->name();
01018     m_name = container->widget()->name();
01019     m_form = container->form();
01020     m_type = container->layoutType();
01021 
01022     for(ObjectTreeItem *tree = container->objectTree()->children()->first(); tree; tree = container->objectTree()->children()->next())
01023     {
01024         QRect r(container->widget()->mapTo(container->widget()->parentWidget(), tree->widget()->pos()), tree->widget()->size());
01025         m_pos.insert(tree->widget()->name(), r);
01026     }
01027 }
01028 
01029 void
01030 BreakLayoutCommand::execute()
01031 {
01032     CreateLayoutCommand::unexecute();
01033 }
01034 
01035 void
01036 BreakLayoutCommand::unexecute()
01037 {
01038     CreateLayoutCommand::execute();
01039 }
01040 
01041 QString
01042 BreakLayoutCommand::name() const
01043 {
01044     return i18n("Break Layout: \"%1\"").arg(m_name);
01045 }
01046 
01047 void
01048 BreakLayoutCommand::debug()
01049 {
01050     kdDebug() << "BreakLayoutCommand: name=\"" << name()
01051         << " widgets=" << m_pos.keys() << " container=" << m_containername
01052         << " form=" << m_form->widget()->name() << endl;
01053 }
01054 
01055 // PasteWidgetCommand
01056 
01057 PasteWidgetCommand::PasteWidgetCommand(QDomDocument &domDoc, Container *container, const QPoint& p)
01058  : m_point(p)
01059 {
01060     m_data = domDoc.toCString();
01061     m_containername = container->widget()->name();
01062     m_form = container->form();
01063 
01064     if(domDoc.namedItem("UI").firstChild().nextSibling().toElement().tagName() != "widget")
01065         return;
01066 
01067     QRect boundingRect;
01068     for(QDomNode n = domDoc.namedItem("UI").firstChild(); !n.isNull(); n = n.nextSibling()) // more than one widget
01069     {
01070         if(n.toElement().tagName() != "widget")
01071             continue;
01072         QDomElement el = n.toElement();
01073 
01074         QDomElement rect;
01075         for(QDomNode n = el.firstChild(); !n.isNull(); n = n.nextSibling())
01076         {
01077             if((n.toElement().tagName() == "property") && (n.toElement().attribute("name") == "geometry"))
01078                 rect = n.firstChild().toElement();
01079         }
01080 
01081         QDomElement x = rect.namedItem("x").toElement();
01082         QDomElement y = rect.namedItem("y").toElement();
01083         QDomElement wi = rect.namedItem("width").toElement();
01084         QDomElement h = rect.namedItem("height").toElement();
01085 
01086         int rx = x.text().toInt();
01087         int ry = y.text().toInt();
01088         int rw = wi.text().toInt();
01089         int rh = h.text().toInt();
01090         QRect r(rx, ry, rw, rh);
01091         boundingRect = boundingRect.unite(r);
01092     }
01093 
01094     m_point = m_point - boundingRect.topLeft();
01095 }
01096 
01097 void
01098 PasteWidgetCommand::execute()
01099 {
01100     ObjectTreeItem* titem = m_form->objectTree()->lookup(m_containername);
01101     if (!titem)
01102         return; //better this than a crash
01103     Container *container = titem->container();
01104     QString errMsg;
01105     int errLine;
01106     int errCol;
01107     QDomDocument domDoc("UI");
01108     bool parsed = domDoc.setContent(m_data, false, &errMsg, &errLine, &errCol);
01109 
01110     if(!parsed)
01111     {
01112         kdDebug() << "WidgetWatcher::load(): " << errMsg << endl;
01113         kdDebug() << "WidgetWatcher::load(): line: " << errLine << " col: " << errCol << endl;
01114         return;
01115     }
01116 
01117     //FormIO::setCurrentForm(m_container->form());
01118 
01119     kdDebug() << domDoc.toString() << endl;
01120     if(!domDoc.namedItem("UI").hasChildNodes()) // nothing in the doc
01121         return;
01122     if(domDoc.namedItem("UI").firstChild().nextSibling().toElement().tagName() != "widget") // only one widget, so we can paste it at cursor pos
01123     {
01124         QDomElement el = domDoc.namedItem("UI").firstChild().toElement();
01125         fixNames(el);
01126         if(m_point.isNull())
01127             fixPos(el, container);
01128         else
01129             changePos(el, m_point);
01130 
01131         m_form->setInteractiveMode(false);
01132         FormIO::loadWidget(container, el);
01133         m_form->setInteractiveMode(true);
01134     }
01135     else for(QDomNode n = domDoc.namedItem("UI").firstChild(); !n.isNull(); n = n.nextSibling()) // more than one widget
01136     {
01137         if(n.toElement().tagName() != "widget")
01138             continue;
01139         QDomElement el = n.toElement();
01140         fixNames(el);
01141         if(!m_point.isNull())
01142             moveWidgetBy(el, container, m_point);
01143         else {
01144             fixPos(el, container);
01145             kdDebug() << "jdkjfldfksmfkdfjmqdsklfjdkkfmsqfksdfsm" << endl;
01146         }
01147 
01148         m_form->setInteractiveMode(false);
01149         FormIO::loadWidget(container, el);
01150         m_form->setInteractiveMode(true);
01151     }
01152 
01153     //FormIO::setCurrentForm(0);
01154     m_names.clear();
01155     // We store the names of all the created widgets, to delete them later
01156     for(QDomNode n = domDoc.namedItem("UI").firstChild(); !n.isNull(); n = n.nextSibling())
01157     {
01158         if(n.toElement().tagName() != "widget")
01159             continue;
01160         for(QDomNode m = n.firstChild(); !m.isNull(); n = m.nextSibling())
01161         {
01162             if((m.toElement().tagName() == "property") && (m.toElement().attribute("name") == "name"))
01163             {
01164                 m_names.append(m.toElement().text());
01165                 break;
01166             }
01167         }
01168     }
01169 
01170     container->form()->selectFormWidget();
01171     QStringList::ConstIterator endIt = m_names.constEnd();
01172     for(QStringList::ConstIterator it = m_names.constBegin(); it != endIt; ++it) // We select all the pasted widgets
01173     {
01174         ObjectTreeItem *item = m_form->objectTree()->lookup(*it);
01175         if(item)
01176             container->setSelectedWidget(item->widget(), true);
01177     }
01178 }
01179 
01180 void
01181 PasteWidgetCommand::unexecute()
01182 {
01183     ObjectTreeItem* titem = m_form->objectTree()->lookup(m_containername);
01184     if (!titem)
01185         return; //better this than a crash
01186     Container *container = titem->container();
01187     // We just delete all the widgets we have created
01188     QStringList::ConstIterator endIt = m_names.constEnd();
01189     for(QStringList::ConstIterator it = m_names.constBegin(); it != endIt; ++it)
01190     {
01191         ObjectTreeItem* titem = container->form()->objectTree()->lookup(*it);
01192         if (!titem)
01193             continue; //better this than a crash
01194         QWidget *w = titem->widget();
01195         container->deleteWidget(w);
01196     }
01197 }
01198 
01199 QString
01200 PasteWidgetCommand::name() const
01201 {
01202     return i18n("Paste");
01203 }
01204 
01205 void
01206 //QDomElement
01207 PasteWidgetCommand::changePos(QDomElement &el, const QPoint &newpos)
01208 {
01209     //QDomElement el = widg.cloneNode(true).toElement();
01210     QDomElement rect;
01211     // Find the widget geometry if there is one
01212     for(QDomNode n = el.firstChild(); !n.isNull(); n = n.nextSibling())
01213     {
01214         if((n.toElement().tagName() == "property") && (n.toElement().attribute("name") == "geometry"))
01215             rect = n.firstChild().toElement();
01216     }
01217 
01218     QDomElement x = rect.namedItem("x").toElement();
01219     x.removeChild(x.firstChild());
01220     QDomText valueX = el.ownerDocument().createTextNode(QString::number(newpos.x()));
01221     x.appendChild(valueX);
01222 
01223     QDomElement y = rect.namedItem("y").toElement();
01224     y.removeChild(y.firstChild());
01225     QDomText valueY = el.ownerDocument().createTextNode(QString::number(newpos.y()));
01226     y.appendChild(valueY);
01227 
01228     //return el;
01229 }
01230 
01231 void
01232 PasteWidgetCommand::fixPos(QDomElement &el, Container *container)
01233 {
01234 /*  QDomElement rect;
01235     for(QDomNode n = el.firstChild(); !n.isNull(); n = n.nextSibling())
01236     {
01237         if((n.toElement().tagName() == "property") && (n.toElement().attribute("name") == "geometry"))
01238             rect = n.firstChild().toElement();
01239     }
01240 
01241     QDomElement x = rect.namedItem("x").toElement();
01242     QDomElement y = rect.namedItem("y").toElement();
01243     QDomElement wi = rect.namedItem("width").toElement();
01244     QDomElement h = rect.namedItem("height").toElement();
01245 
01246     int rx = x.text().toInt();
01247     int ry = y.text().toInt();
01248     int rw = wi.text().toInt();
01249     int rh = h.text().toInt();
01250     QRect r(rx, ry, rw, rh);
01251 
01252     QWidget *w = m_form->widget()->childAt(r.x() + 6, r.y() + 6, false);
01253     if(!w)
01254         return;
01255 
01256     while((w->geometry() == r) && (w != 0))// there is already a widget there, with the same size
01257     {
01258         w = m_form->widget()->childAt(w->x() + 16, w->y() + 16, false);
01259         r.moveBy(10,10);
01260     }
01261 
01262     // the pasted wigdet should stay inside container's boundaries
01263     if(r.x() < 0)
01264         r.moveLeft(0);
01265     else if(r.right() > container->widget()->width())
01266         r.moveLeft(container->widget()->width() - r.width());
01267 
01268     if(r.y() < 0)
01269         r.moveTop(0);
01270     else if(r.bottom() > container->widget()->height())
01271         r.moveTop(container->widget()->height() - r.height());
01272 
01273     if(r != QRect(rx, ry, rw, rh))
01274         //return el;
01275     //else
01276         changePos(el, QPoint(r.x(), r.y()));
01277 */
01278     moveWidgetBy(el, container, QPoint(0, 0));
01279 }
01280 
01281 void
01282 PasteWidgetCommand::moveWidgetBy(QDomElement &el, Container *container, const QPoint &p)
01283 {
01284     QDomElement rect;
01285     for(QDomNode n = el.firstChild(); !n.isNull(); n = n.nextSibling())
01286     {
01287         if((n.toElement().tagName() == "property") && (n.toElement().attribute("name") == "geometry"))
01288             rect = n.firstChild().toElement();
01289     }
01290 
01291     QDomElement x = rect.namedItem("x").toElement();
01292     QDomElement y = rect.namedItem("y").toElement();
01293     QDomElement wi = rect.namedItem("width").toElement();
01294     QDomElement h = rect.namedItem("height").toElement();
01295 
01296     int rx = x.text().toInt();
01297     int ry = y.text().toInt();
01298     int rw = wi.text().toInt();
01299     int rh = h.text().toInt();
01300     QRect r(rx + p.x(), ry + p.y(), rw, rh);
01301     kdDebug() << "Moving widget by " << p << " from " << rx << "  " << ry << " to " << r.topLeft() << endl;
01302 
01303     QWidget *w = m_form->widget()->childAt(r.x() + 6, r.y() + 6, false);
01304 
01305     while(w && (w->geometry() == r))// there is already a widget there, with the same size
01306     {
01307         w = m_form->widget()->childAt(w->x() + 16, w->y() + 16, false);
01308         r.moveBy(10,10);
01309     }
01310 
01311     // the pasted wigdet should stay inside container's boundaries
01312     if(r.x() < 0)
01313         r.moveLeft(0);
01314     else if(r.right() > container->widget()->width())
01315         r.moveLeft(container->widget()->width() - r.width());
01316 
01317     if(r.y() < 0)
01318         r.moveTop(0);
01319     else if(r.bottom() > container->widget()->height())
01320         r.moveTop(container->widget()->height() - r.height());
01321 
01322     if(r != QRect(rx, ry, rw, rh))
01323         //return el;
01324     //else
01325         changePos(el, QPoint(r.x(), r.y()));
01326 }
01327 
01328 void
01329 PasteWidgetCommand::fixNames(QDomElement &el)
01330 {
01331     QString wname;
01332     for(QDomNode n = el.firstChild(); !n.isNull(); n = n.nextSibling())
01333     {
01334         if((n.toElement().tagName() == "property") && (n.toElement().attribute("name") == "name"))
01335         {
01336             wname = n.toElement().text();
01337             while(m_form->objectTree()->lookup(wname)) // name already exists
01338             {
01339                 bool ok;
01340                 int num = wname.right(1).toInt(&ok, 10);
01341                 if(ok)
01342                     wname = wname.left(wname.length()-1) + QString::number(num+1);
01343                 else
01344                     wname += "2";
01345             }
01346             if(wname != n.toElement().text()) // we change the name, so we recreate the element
01347             {
01348                 n.removeChild(n.firstChild());
01349                 QDomElement type = el.ownerDocument().createElement("string");
01350                 QDomText valueE = el.ownerDocument().createTextNode(wname);
01351                 type.appendChild(valueE);
01352                 n.toElement().appendChild(type);
01353             }
01354 
01355         }
01356         if(n.toElement().tagName() == "widget") // fix child widgets names
01357         {
01358             QDomElement child = n.toElement();
01359             fixNames(child);
01360         }
01361     }
01362 }
01363 
01364 void
01365 PasteWidgetCommand::debug()
01366 {
01367     kdDebug() << "PasteWidgetCommand: pos=" << m_point
01368         << " widgets=" << m_names << " container=" << m_containername
01369         << " form=" << m_form->widget()->name() 
01370         << " data=\"" << m_data.left(80) << "...\"" << endl;
01371 }
01372 
01373 // DeleteWidgetCommand
01374 
01375 DeleteWidgetCommand::DeleteWidgetCommand(WidgetList &list, Form *form)
01376  : Command(), m_form(form)
01377 {
01378     m_domDoc = QDomDocument("UI");
01379     m_domDoc.appendChild(m_domDoc.createElement("UI"));
01380 
01381     QDomElement parent = m_domDoc.namedItem("UI").toElement();
01382 
01383     //for(QWidget *w = list.first(); w; w = list.next())
01384     /*for(WidgetListIterator it(list); it.current() != 0; ++it)
01385     {
01386         QWidget *w = it.current();
01387         // Don't delete tabwidget or widgetstack pages
01388         if(w->parentWidget()->inherits("QWidgetStack"))
01389         {
01390             list.remove(w);
01391             continue;
01392         }
01393     }*/
01394     removeChildrenFromList(list);
01395 
01396     for(WidgetListIterator it(list); it.current() != 0; ++it)
01397     {
01398         ObjectTreeItem *item = m_form->objectTree()->lookup(it.current()->name());
01399         if (!item)
01400             return;
01401 
01402         // We need to store both parentContainer and parentWidget as they may be different (eg for TabWidget page)
01403         m_containers.insert(item->name().latin1(), m_form->parentContainer(item->widget())->widget()->name());
01404         m_parents.insert(item->name().latin1(), item->parent()->name().latin1());
01405         FormIO::saveWidget(item, parent, m_domDoc);
01406         form->connectionBuffer()->saveAllConnectionsForWidget(item->widget()->name(), m_domDoc);
01407     }
01408 
01409     FormIO::cleanClipboard(parent);
01410 }
01411 
01412 void
01413 DeleteWidgetCommand::execute()
01414 {
01415     Container *containerToSelect = 0;
01416 
01417     QMap<QCString,QCString>::ConstIterator endIt = m_containers.constEnd();
01418     for(QMap<QCString,QCString>::ConstIterator  it = m_containers.constBegin(); it != endIt; ++it)
01419     {
01420         ObjectTreeItem *item = m_form->objectTree()->lookup(it.key());
01421         if (!item || !item->widget())
01422             continue;
01423 
01424         Container *cont = m_form->parentContainer(item->widget());
01425         if (!containerToSelect)
01426             containerToSelect = cont;
01427         cont->deleteWidget(item->widget());
01428     }
01429     //now we've nothing selecte: select parent container
01430     if (containerToSelect)
01431         m_form->setSelectedWidget( containerToSelect->widget() );
01432 }
01433 
01434 void
01435 DeleteWidgetCommand::unexecute()
01436 {
01437     QCString wname;
01438     m_form->setInteractiveMode(false);
01439     for(QDomNode n = m_domDoc.namedItem("UI").firstChild(); !n.isNull(); n = n.nextSibling())
01440     {
01441         if(n.toElement().tagName() == "connections") // restore the widget connections
01442             m_form->connectionBuffer()->load(n);
01443         if(n.toElement().tagName() != "widget")
01444             continue;
01445         // We need first to know the name of the widget
01446         for(QDomNode m = n.firstChild(); !m.isNull(); n = m.nextSibling())
01447         {
01448             if((m.toElement().tagName() == "property") && (m.toElement().attribute("name") == "name"))
01449             {
01450                 wname = m.toElement().text().latin1();
01451                 break;
01452             }
01453         }
01454 
01455         ObjectTreeItem* titem = m_form->objectTree()->lookup(m_containers[wname]);
01456         if (!titem)
01457             return; //better this than a crash
01458         Container *cont = titem->container();
01459         ObjectTreeItem *parent = m_form->objectTree()->lookup(m_parents[wname]);
01460         QDomElement widg = n.toElement();
01461         if(parent)
01462             FormIO::loadWidget(cont, widg, parent->widget());
01463         else
01464             FormIO::loadWidget(cont, widg);
01465     }
01466     m_form->setInteractiveMode(true);
01467 }
01468 
01469 QString
01470 DeleteWidgetCommand::name() const
01471 {
01472     return i18n("Delete widget");
01473 }
01474 
01475 void
01476 DeleteWidgetCommand::debug()
01477 {
01478     kdDebug() << "DeleteWidgetCommand: containers=" << m_containers.keys()
01479         << " parents=" << m_parents.keys() << " form=" << m_form->widget()->name() << endl;
01480 }
01481 
01482 // CutWidgetCommand
01483 
01484 CutWidgetCommand::CutWidgetCommand(WidgetList &list, Form *form)
01485  : DeleteWidgetCommand(list, form)
01486 {}
01487 
01488 void
01489 CutWidgetCommand::execute()
01490 {
01491     DeleteWidgetCommand::execute();
01492     m_data = FormManager::self()->m_domDoc.toCString();
01493     FormManager::self()->m_domDoc.setContent(m_domDoc.toCString());
01494 }
01495 
01496 void
01497 CutWidgetCommand::unexecute()
01498 {
01499     DeleteWidgetCommand::unexecute();
01500     FormManager::self()->m_domDoc.setContent(m_data);
01501 }
01502 
01503 QString
01504 CutWidgetCommand::name() const
01505 {
01506     return i18n("Cut");
01507 }
01508 
01509 void
01510 CutWidgetCommand::debug()
01511 {
01512     kdDebug() << "CutWidgetCommand: containers=" << m_containers.keys()
01513         << " parents=" << m_parents.keys() << " form=" << m_form->widget()->name()
01514         << " data=\"" << m_data.left(80) << "...\"" << endl;
01515 }
01516 
01517 // CommandGroup
01518 
01519 namespace KFormDesigner {
01520 class CommandGroup::SubCommands : public KMacroCommand
01521 {
01522     public:
01523         SubCommands( const QString & name )
01524          : KMacroCommand(name)
01525         {
01526         }
01527         const QPtrList<KCommand>& commands() const { return m_commands; }
01528 };
01529 }
01530 
01531 CommandGroup::CommandGroup( const QString & name, WidgetPropertySet *propSet )
01532     : Command()
01533     , m_subCommands(new SubCommands(name))
01534     , m_propSet(propSet)
01535 {
01536 }
01537 
01538 CommandGroup::~CommandGroup()
01539 {
01540     delete m_subCommands;
01541 }
01542 
01543 const QPtrList<KCommand>& CommandGroup::commands() const
01544 {
01545     return m_subCommands->commands();
01546 }
01547 
01548 void CommandGroup::addCommand(KCommand *command, bool allowExecute)
01549 {
01550     if (!command)
01551         return;
01552 
01553     m_subCommands->addCommand(command);
01554     if (!allowExecute)
01555         m_commandsShouldntBeExecuted.insert(command, (char*)1);
01556 }
01557 
01558 void CommandGroup::execute()
01559 {
01560     FormManager::self()->blockPropertyEditorUpdating(this);
01561     for (QPtrListIterator<KCommand> it(m_subCommands->commands()); it.current(); ++it) {
01562         if (!m_commandsShouldntBeExecuted[it.current()])
01563             it.current()->execute();
01564     }
01565     FormManager::self()->unblockPropertyEditorUpdating(this, m_propSet);
01566 }
01567 
01568 void CommandGroup::unexecute()
01569 {
01570     FormManager::self()->blockPropertyEditorUpdating(this);
01571     m_subCommands->unexecute();
01572     FormManager::self()->unblockPropertyEditorUpdating(this, m_propSet);
01573 }
01574 
01575 QString CommandGroup::name() const
01576 {
01577     return m_subCommands->name();
01578 }
01579 
01580 void CommandGroup::resetAllowExecuteFlags()
01581 {
01582     m_commandsShouldntBeExecuted.clear();
01583 }
01584 
01585 void
01586 CommandGroup::debug()
01587 {
01588     kdDebug() << "*CommandGroup: name=\"" << name() << "\" #=" << m_subCommands->commands().count() << endl;
01589     uint i = 1;
01590     for (QPtrListIterator<KCommand> it(m_subCommands->commands()); it.current(); ++it, i++) {
01591         kdDebug() << "#" << i << ":" 
01592             << (m_commandsShouldntBeExecuted[it.current()] ? "!" : "") << "allowExecute:" << endl;
01593         if (dynamic_cast<Command*>(it.current()))
01594             dynamic_cast<Command*>(it.current())->debug();
01595         else if (dynamic_cast<CommandGroup*>(it.current()))
01596             dynamic_cast<CommandGroup*>(it.current())->debug();
01597         else
01598             kdDebug() << "(other KCommand)" << endl;
01599     }
01600     kdDebug() << "End of CommandGroup" << endl;
01601 }
KDE Home | KDE Accessibility Home | Description of Access Keys