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