kexi

form.cpp

00001 /* This file is part of the KDE project
00002    Copyright (C) 2003 Lucijan Busch <lucijan@gmx.at>
00003    Copyright (C) 2004 Cedric Pasteur <cedric.pasteur@free.fr>
00004    Copyright (C) 2004-2005 Jaroslaw Staniek <js@iidea.pl>
00005 
00006    This library is free software; you can redistribute it and/or
00007    modify it under the terms of the GNU Library General Public
00008    License as published by the Free Software Foundation; either
00009    version 2 of the License, or (at your option) any later version.
00010 
00011    This library is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014    Library General Public License for more details.
00015 
00016    You should have received a copy of the GNU Library General Public License
00017    along with this library; see the file COPYING.LIB.  If not, write to
00018    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00019  * Boston, MA 02110-1301, USA.
00020 */
00021 
00022 #include <qwidget.h>
00023 #include <qlabel.h>
00024 #include <qobjectlist.h>
00025 
00026 #include <kdebug.h>
00027 #include <klocale.h>
00028 #include <kcommand.h>
00029 #include <kaction.h>
00030 #include <kmessagebox.h>
00031 
00032 #include "container.h"
00033 #include "objecttree.h"
00034 #include "widgetpropertyset.h"
00035 #include "formIO.h"
00036 #include "formmanager.h"
00037 #include "widgetlibrary.h"
00038 #include "spring.h"
00039 #include "pixmapcollection.h"
00040 #include "events.h"
00041 #include "utils.h"
00042 #include <koproperty/property.h>
00043 
00044 #include "form.h"
00045 
00046 using namespace KFormDesigner;
00047 
00048 FormPrivate::FormPrivate()
00049 {
00050     toplevel = 0;
00051     topTree = 0;
00052     widget = 0;
00053     resizeHandles.setAutoDelete(true);
00054     dirty = false;
00055     interactive = true;
00056     design = true;
00057     autoTabstops = false;
00058     tabstops.setAutoDelete(false);
00059     connBuffer = new ConnectionBuffer();
00060     formatVersion = KFormDesigner::version();
00061     originalFormatVersion = KFormDesigner::version();
00062 }
00063 
00064 FormPrivate::~FormPrivate()
00065 {
00066     delete history;
00067     delete topTree;
00068     delete connBuffer;
00069     connBuffer = 0;
00070     resizeHandles.setAutoDelete(false);
00071     // otherwise, it tries to delete widgets which doesn't exist anymore
00072 }
00073 
00074 //--------------------------------------
00075 
00076 FormWidget::FormWidget()
00077  : m_form(0)
00078 {
00079 }
00080 
00081 FormWidget::~FormWidget()
00082 {
00083     if (m_form) {
00084         m_form->setFormWidget(0);
00085     }
00086 }
00087 
00088 //--------------------------------------
00089 
00090 Form::Form(WidgetLibrary* library, const char *name, bool designMode)
00091   : QObject(library, name)
00092   , m_lib(library)
00093 {
00094     d = new FormPrivate();
00095 //  d->manager = manager;
00096     d->design = designMode;
00097 
00098     // Init actions
00099     d->collection = new KActionCollection(0, this);
00100     d->history = new KCommandHistory(d->collection, true);
00101     connect(d->history, SIGNAL(commandExecuted()), this, SLOT(slotCommandExecuted()));
00102     connect(d->history, SIGNAL(documentRestored()), this, SLOT(slotFormRestored()));
00103 }
00104 
00105 Form::~Form()
00106 {
00107     emit destroying();
00108     delete d;
00109     d = 0;
00110 }
00111 
00112 QWidget*
00113 Form::widget() const
00114 {
00115     if(d->topTree)
00116         return d->topTree->widget();
00117     else if(d->toplevel)
00118         return d->toplevel->widget();
00119     else // preview form
00120         return d->widget;
00121 }
00122 
00124 
00125 void
00126 Form::createToplevel(QWidget *container, FormWidget *formWidget, const QCString &)
00127 {
00128     kdDebug() << "Form::createToplevel() container= "<< (container ? container->name() : "<NULL>")
00129         << " formWidget=" << formWidget << "className=" << name() << endl;
00130 
00131     setFormWidget( formWidget );
00132     d->toplevel = new Container(0, container, this, name());
00133     d->topTree = new ObjectTree(i18n("Form"), container->name(), container, d->toplevel);
00134     d->toplevel->setObjectTree(d->topTree);
00135     d->toplevel->setForm(this);
00136     d->pixcollection = new PixmapCollection(container->name(), this);
00137 
00138     d->topTree->setWidget(container);
00140 //  d->topTree->addModifiedProperty("caption", name());
00141     //m_topTree->addModifiedProperty("icon");
00142 
00143     connect(container, SIGNAL(destroyed()), this, SLOT(formDeleted()));
00144 
00145     kdDebug() << "Form::createToplevel(): d->toplevel=" << d->toplevel << endl;
00146 }
00147 
00148 
00149 Container*
00150 Form::activeContainer()
00151 {
00152     ObjectTreeItem *it;
00153     if(d->selected.count() == 0)
00154         return d->toplevel;
00155 
00156     if(d->selected.count() == 1)
00157         it = d->topTree->lookup(d->selected.last()->name());
00158     else
00159         it = commonParentContainer( &(d->selected) );
00160 
00161     if (!it)
00162         return 0;
00163     if(it->container())
00164         return it->container();
00165     else
00166         return it->parent()->container();
00167 }
00168 
00169 ObjectTreeItem*
00170 Form::commonParentContainer(WidgetList *wlist)
00171 {
00172     ObjectTreeItem *item = 0;
00173     WidgetList *list = new WidgetList();
00174 
00175     // Creates a list of all widget parents
00176     for(QWidget *w = wlist->first(); w; w = wlist->next())
00177     {
00178         if(list->findRef(w->parentWidget()) == -1)
00179             list->append(w->parentWidget());
00180     }
00181 
00182     removeChildrenFromList(*list);
00183 
00184     // one widget remains == the container we are looking for
00185     if(list->count() == 1)
00186         item = d->topTree->lookup(list->first()->name());
00187     else // we need to go one level up
00188         item =  commonParentContainer(list);
00189 
00190     delete list;
00191     return item;
00192 }
00193 
00194 Container*
00195 Form::parentContainer(QWidget *w)
00196 {
00197     ObjectTreeItem *it;
00198     if(!w)
00199         return 0;
00200     //  it = d->topTree->lookup(d->selected.last()->name());
00201     //else
00202     it = d->topTree->lookup(w->name());
00203 
00204     if(it->parent()->container())
00205         return it->parent()->container();
00206     else
00207         return it->parent()->parent()->container();
00208 }
00209 
00210 
00211 
00212 void
00213 Form::setDesignMode(bool design)
00214 {
00215     d->design = design;
00216     if(!design)
00217     {
00218         ObjectTreeDict *dict = new ObjectTreeDict( *(d->topTree->dict()) );
00219         ObjectTreeDictIterator it(*dict);
00220         for(; it.current(); ++it)
00221             m_lib->previewWidget(it.current()->widget()->className(), it.current()->widget(), d->toplevel);
00222         delete dict;
00223 
00224         d->widget = d->topTree->widget();
00225         delete (d->topTree);
00226         d->topTree = 0;
00227         delete (d->toplevel);
00228         d->toplevel = 0;
00229     }
00230 }
00231 
00232 
00234 
00235 void
00236 Form::setSelectedWidget(QWidget *w, bool add, bool dontRaise)
00237 {
00238     if((d->selected.isEmpty()) || (w == widget()) || (d->selected.first() == widget()))
00239         add = false;
00240 
00241     if(!w)
00242     {
00243         setSelectedWidget(widget());
00244         return;
00245     }
00246 
00247     //raise selected widget and all possible parents
00248     QWidget *wtmp = w;
00249     while(!dontRaise && wtmp && wtmp->parentWidget() && (wtmp != widget()))
00250     {
00251         wtmp->raise();
00252         if(d->resizeHandles[ wtmp->name() ])
00253             d->resizeHandles[ wtmp->name() ]->raise();
00254         wtmp = wtmp->parentWidget();
00255     }
00256 
00257     if (wtmp)
00258         wtmp->setFocus();
00259 
00260     if(!add)
00261     {
00262         d->selected.clear();
00263         d->resizeHandles.clear();
00264     }
00265     d->selected.append(w);
00266     emit selectionChanged(w, add);
00267     emitActionSignals(false);
00268 
00269     // WidgetStack and TabWidget pages widgets shouldn't have resize handles, but their parent
00270     if(!FormManager::self()->isTopLevel(w) && w->parentWidget() && w->parentWidget()->isA("QWidgetStack"))
00271     {
00272         w = w->parentWidget();
00273         if(w->parentWidget() && w->parentWidget()->inherits("QTabWidget"))
00274             w = w->parentWidget();
00275     }
00276 
00277     if(w && w != widget())
00278         d->resizeHandles.insert(w->name(), new ResizeHandleSet(w, this));
00279 }
00280 
00281 ResizeHandleSet*
00282 Form::resizeHandlesForWidget(QWidget* w)
00283 {
00284     return d->resizeHandles[w->name()];
00285 }
00286 
00287 void
00288 Form::unSelectWidget(QWidget *w)
00289 {
00290     d->selected.remove(w);
00291     d->resizeHandles.remove(w->name());
00292 }
00293 
00294 void
00295 Form::selectFormWidget()
00296 {
00297     setSelectedWidget(widget(), false);
00298 }
00299 
00300 void
00301 Form::clearSelection()
00302 {
00303     d->selected.clear();
00304     d->resizeHandles.clear();
00305     emit selectionChanged(0, false);
00306     emitActionSignals(false);
00307 }
00308 
00309 void
00310 Form::emitActionSignals(bool withUndoAction)
00311 {
00312     // Update menu and toolbar items
00313     if(d->selected.count() > 1)
00314         FormManager::self()->emitWidgetSelected(this, true);
00315     else if(d->selected.first() != widget())
00316         FormManager::self()->emitWidgetSelected(this, false);
00317     else
00318         FormManager::self()->emitFormWidgetSelected(this);
00319 
00320     if(!withUndoAction)
00321         return;
00322 
00323     KAction *undoAction = d->collection->action("edit_undo");
00324     if(undoAction)
00325         FormManager::self()->emitUndoEnabled(undoAction->isEnabled(), undoAction->text());
00326 
00327     KAction *redoAction = d->collection->action("edit_redo");
00328     if(redoAction)
00329         FormManager::self()->emitRedoEnabled(redoAction->isEnabled(), redoAction->text());
00330 }
00331 
00332 void
00333 Form::emitSelectionSignals()
00334 {
00335     emit selectionChanged(selectedWidgets()->first(), false);
00336 //  for(QWidget *w = selectedWidgets()->next(); w; w = selectedWidgets()->next())
00337 //      emit selectionChanged(selectedWidgets()->first(), true);
00338     for (WidgetListIterator it(*selectedWidgets()); it.current(); ++it)
00339         emit selectionChanged(it.current(), true);
00340 }
00341 
00343 void
00344 Form::formDeleted()
00345 {
00346 //  clearSelection();
00347     d->selected.clear();
00348     d->resizeHandles.setAutoDelete(false);
00349     d->resizeHandles.clear();
00350     d->resizeHandles.setAutoDelete(true);
00351 //  emit selectionChanged(0, false);
00352 //  emitActionSignals(false);
00353 
00354     FormManager::self()->deleteForm(this);
00355     //delete this;
00356     deleteLater();
00357 }
00358 
00359 void
00360 Form::changeName(const QCString &oldname, const QCString &newname)
00361 {
00362     if(oldname == newname)
00363         return;
00364     if(!d->topTree->rename(oldname, newname)) // rename failed
00365     {
00366         KMessageBox::sorry(widget()->topLevelWidget(),
00367             i18n("Renaming widget \"%1\" to \"%2\" failed.").arg(oldname).arg(newname));
00368 //moved to WidgetPropertySet::slotChangeProperty()
00369 //      KMessageBox::sorry(widget()->topLevelWidget(),
00370 //      i18n("A widget with this name already exists. "
00371 //          "Please choose another name or rename existing widget."));
00372         kdDebug() << "Form::changeName() : ERROR : A widget named " << newname << " already exists" << endl;
00373         FormManager::self()->propertySet()->property("name") = QVariant(oldname);
00374     }
00375     else
00376     {
00377         d->connBuffer->fixName(oldname, newname);
00378         ResizeHandleSet *temp = d->resizeHandles.take(oldname);
00379         d->resizeHandles.insert(newname, temp);
00380     }
00381 }
00382 
00383 void
00384 Form::emitChildAdded(ObjectTreeItem *item)
00385 {
00386     addWidgetToTabStops(item);
00387     emit childAdded(item);
00388 }
00389 
00390 void
00391 Form::emitChildRemoved(ObjectTreeItem *item)
00392 {
00393     d->tabstops.remove(item);
00394     if(d->connBuffer)
00395         d->connBuffer->removeAllConnectionsForWidget(item->name());
00396     emit childRemoved(item);
00397 }
00398 
00399 void
00400 Form::addCommand(KCommand *command, bool execute)
00401 {
00402     emit FormManager::self()->dirty(this, true);
00403     d->dirty = true;
00404     d->history->addCommand(command, execute);
00405     if(!execute) // simulate command to activate 'undo' menu
00406         slotCommandExecuted();
00407 }
00408 
00409 void
00410 Form::clearCommandHistory()
00411 {
00412     d->history->clear();
00413     FormManager::self()->emitUndoEnabled(false, QString::null); 
00414     FormManager::self()->emitRedoEnabled(false, QString::null); 
00415 }
00416 
00417 void
00418 Form::slotCommandExecuted()
00419 {
00420     emit FormManager::self()->dirty(this, true);
00421     d->dirty = true;
00422     // because actions text is changed after the commandExecuted() signal is emitted
00423     QTimer::singleShot(10, this, SLOT(emitUndoEnabled()));
00424     QTimer::singleShot(10, this, SLOT(emitRedoEnabled()));
00425 }
00426 
00427 void
00428 Form::emitUndoEnabled()
00429 {
00430     KAction *undoAction = d->collection->action("edit_undo");
00431     if(undoAction)
00432         FormManager::self()->emitUndoEnabled(undoAction->isEnabled(), undoAction->text());
00433 }
00434 
00435 void
00436 Form::emitRedoEnabled()
00437 {
00438     KAction *redoAction = d->collection->action("edit_redo");
00439     if(redoAction)
00440         FormManager::self()->emitRedoEnabled(redoAction->isEnabled(), redoAction->text());
00441 }
00442 
00443 void
00444 Form::slotFormRestored()
00445 {
00446     emit FormManager::self()->dirty(this, false);
00447     d->dirty = false;
00448 }
00449 
00450 
00452 
00453 void
00454 Form::addWidgetToTabStops(ObjectTreeItem *c)
00455 {
00456     QWidget *w = c->widget();
00457     if(!w)
00458         return;
00459     if(!(w->focusPolicy() & QWidget::TabFocus))
00460     {
00461         if(!w->children())
00462         return;
00463 
00464         // For composed widgets, we check if one of the child can have focus
00465         QObjectList list = *(w->children());
00466         for(QObject *obj = list.first(); obj; obj = list.next())
00467         {
00468 //          if(obj->isWidgetType() && (((QWidget*)obj)->focusPolicy() != QWidget::NoFocus)) {
00469 //          if(obj->isWidgetType() && (((QWidget*)obj)->focusPolicy() & QWidget::TabFocus)) {
00470             if(obj->isWidgetType()) {//QWidget::TabFocus flag will be checked later!
00471                 if(d->tabstops.findRef(c) == -1) {
00472                     d->tabstops.append(c);
00473                     return;
00474                 }
00475             }
00476         }
00477     }
00478     else if(d->tabstops.findRef(c) == -1) // not yet in the list
00479         d->tabstops.append(c);
00480 }
00481 
00482 void
00483 Form::updateTabStopsOrder()
00484 {
00485     for (ObjectTreeListIterator it(d->tabstops);it.current();) {
00486         if(!(it.current()->widget()->focusPolicy() & QWidget::TabFocus)) {
00487             kexidbg << "Form::updateTabStopsOrder(): widget removed because has no TabFocus: " << it.current()->widget()->name() << endl;
00488             d->tabstops.remove( it.current() );
00489         }
00490         else
00491             ++it;
00492     }
00493 }
00494 
00495 void
00496 Form::autoAssignTabStops()
00497 {
00498     VerWidgetList list;
00499     HorWidgetList hlist;
00500 
00501     foreach_list(ObjectTreeListIterator, it, d->tabstops) {
00502         if(it.current()->widget())
00503             list.append(it.current()->widget());
00504     }
00505 
00506     list.sort();
00507     d->tabstops.clear();
00508 
00511     foreach_list(WidgetListIterator, it, list) {
00512 //  for(WidgetListIterator it(list); it.current() != 0; ++it)
00513         QWidget *w = it.current();
00514         hlist.append(w);
00515 
00516         ++it;
00517         QWidget *nextw = it.current();
00518         while(nextw && (nextw->y() < (w->y() + 20))) {
00519             hlist.append(nextw);
00520             ++it; nextw = it.current();
00521         }
00522         hlist.sort();
00523 
00524         for(WidgetListIterator it2(hlist); it2.current() != 0; ++it2) {
00525             ObjectTreeItem *tree = d->topTree->lookup(it2.current()->name());
00526             if(tree) {
00527                 kdDebug() << "Form::autoAssignTabStops() adding " << tree->name() << endl;
00528                 d->tabstops.append(tree);
00529             }
00530         }
00531 
00532         --it;
00533         hlist.clear();
00534     }
00535 }
00536 
00537 uint Form::formatVersion() const
00538 {
00539     return d->formatVersion;
00540 }
00541 
00542 void Form::setFormatVersion(uint ver)
00543 {
00544     d->formatVersion = ver;
00545 }
00546 uint Form::originalFormatVersion() const
00547 {
00548     return d->originalFormatVersion;
00549 }
00550 
00551 void Form::setOriginalFormatVersion(uint ver)
00552 {
00553     d->originalFormatVersion = ver;
00554 }
00555 
00556 void Form::setFormWidget(FormWidget* w)
00557 {
00558     if (!d)
00559         return;
00560     d->formWidget = w;
00561     if (!d->formWidget)
00562         return;
00563     d->formWidget->m_form = this;
00564 }
00565 
00566 #include "form.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys