form.cpp
1/* This file is part of the KDE project
2 Copyright (C) 2003 Lucijan Busch <lucijan@gmx.at>
3 Copyright (C) 2004 Cedric Pasteur <cedric.pasteur@free.fr>
4 Copyright (C) 2004-2007 Jaroslaw Staniek <js@iidea.pl>
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
15
16 You should have received a copy of the GNU Library General Public License
17 along with this library; see the file COPYING.LIB. If not, write to
18 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20*/
21
22#include <tqwidget.h>
23#include <tqlabel.h>
24#include <tqobjectlist.h>
25#include <tqptrdict.h>
26
27#include <kdebug.h>
28#include <tdelocale.h>
29#include <kcommand.h>
30#include <tdeaction.h>
31#include <tdemessagebox.h>
32
33#include "container.h"
34#include "objecttree.h"
35#include "widgetpropertyset.h"
36#include "formIO.h"
37#include "formmanager.h"
38#include "widgetlibrary.h"
39#include "spring.h"
40#include "pixmapcollection.h"
41#include "events.h"
42#include "utils.h"
43#include "form.h"
44#include <koproperty/property.h>
45#include <kexiutils/utils.h>
46
47using namespace KFormDesigner;
48
49FormPrivate::FormPrivate()
50{
51 toplevel = 0;
52 topTree = 0;
53 widget = 0;
54 resizeHandles.setAutoDelete(true);
55 dirty = false;
56 interactive = true;
57 design = true;
58 autoTabstops = false;
59 tabstops.setAutoDelete(false);
60 connBuffer = new ConnectionBuffer();
61 formatVersion = KFormDesigner::version();
62 originalFormatVersion = KFormDesigner::version();
63}
64
65FormPrivate::~FormPrivate()
66{
67 delete history;
68 delete topTree;
69 delete connBuffer;
70 connBuffer = 0;
71 resizeHandles.setAutoDelete(false);
72 // otherwise, it tries to delete widgets which doesn't exist anymore
73}
74
75//--------------------------------------
76
77FormWidget::FormWidget()
78 : m_form(0)
79{
80}
81
82FormWidget::~FormWidget()
83{
84 if (m_form) {
85 m_form->setFormWidget(0);
86 }
87}
88
89//--------------------------------------
90
91Form::Form(WidgetLibrary* library, const char *name, bool designMode)
92 : TQObject(library, name)
93 , m_lib(library)
94{
95 d = new FormPrivate();
96// d->manager = manager;
97 d->design = designMode;
98
99 // Init actions
100 d->collection = new TDEActionCollection(0, this);
101 d->history = new KCommandHistory(d->collection, true);
102 connect(d->history, TQ_SIGNAL(commandExecuted()), this, TQ_SLOT(slotCommandExecuted()));
103 connect(d->history, TQ_SIGNAL(documentRestored()), this, TQ_SLOT(slotFormRestored()));
104}
105
106Form::~Form()
107{
109 delete d;
110 d = 0;
111}
112
113TQWidget*
115{
116 if(d->topTree)
117 return d->topTree->widget();
118 else if(d->toplevel)
119 return d->toplevel->widget();
120 else // preview form
121 return d->widget;
122}
123
125
126void
127Form::createToplevel(TQWidget *container, FormWidget *formWidget, const TQCString &)
128{
129 kdDebug() << "Form::createToplevel() container= "<< (container ? container->name() : "<NULL>")
130 << " formWidget=" << formWidget << "className=" << name() << endl;
131
132 setFormWidget( formWidget );
133 d->toplevel = new Container(0, container, this, name());
134 d->topTree = new ObjectTree(i18n("Form"), container->name(), container, d->toplevel);
135 d->toplevel->setObjectTree(d->topTree);
136 d->toplevel->setForm(this);
137 d->pixcollection = new PixmapCollection(container->name(), this);
138
139 d->topTree->setWidget(container);
141// d->topTree->addModifiedProperty("caption", name());
142 //m_topTree->addModifiedProperty("icon");
143
144 connect(container, TQ_SIGNAL(destroyed()), this, TQ_SLOT(formDeleted()));
145
146 kdDebug() << "Form::createToplevel(): d->toplevel=" << d->toplevel << endl;
147}
148
149
152{
154 if(d->selected.count() == 0)
155 return d->toplevel;
156
157 if(d->selected.count() == 1)
158 it = d->topTree->lookup(d->selected.last()->name());
159 else
160 it = commonParentContainer( &(d->selected) );
161
162 if (!it)
163 return 0;
164 if(it->container())
165 return it->container();
166 else
167 return it->parent()->container();
168}
169
172{
173 ObjectTreeItem *item = 0;
174 WidgetList *list = new WidgetList();
175
176 // Creates a list of all widget parents
177 for(TQWidget *w = wlist->first(); w; w = wlist->next())
178 {
179 if(list->findRef(w->parentWidget()) == -1)
180 list->append(w->parentWidget());
181 }
182
184
185 // one widget remains == the container we are looking for
186 if(list->count() == 1)
187 item = d->topTree->lookup(list->first()->name());
188 else // we need to go one level up
189 item = commonParentContainer(list);
190
191 delete list;
192 return item;
193}
194
197{
199 if(!w)
200 return 0;
201 // it = d->topTree->lookup(d->selected.last()->name());
202 //else
203 it = d->topTree->lookup(w->name());
204
205 if(it->parent()->container())
206 return it->parent()->container();
207 else
208 return it->parent()->parent()->container();
209}
210
211
212
213void
215{
216 d->design = design;
217 if(!design)
218 {
219 ObjectTreeDict *dict = new ObjectTreeDict( *(d->topTree->dict()) );
221 for(; it.current(); ++it)
222 m_lib->previewWidget(it.current()->widget()->className(), it.current()->widget(), d->toplevel);
223 delete dict;
224
225 d->widget = d->topTree->widget();
226 delete (d->topTree);
227 d->topTree = 0;
228 delete (d->toplevel);
229 d->toplevel = 0;
230 }
231}
232
233
235
236void
238{
239 if((d->selected.isEmpty()) || (w == widget()) || (d->selected.first() == widget()))
240 add = false;
241
242 if(!w)
243 {
245 return;
246 }
247
248 //raise selected widget and all possible parents
249 TQWidget *wtmp = w;
250 while(!dontRaise && wtmp && wtmp->parentWidget() && (wtmp != widget()))
251 {
252 wtmp->raise();
253 if(d->resizeHandles[ wtmp->name() ])
254 d->resizeHandles[ wtmp->name() ]->raise();
255 wtmp = wtmp->parentWidget();
256 }
257
258 if (wtmp)
259 wtmp->setFocus();
260
261 if(!add)
262 {
263 d->selected.clear();
264 d->resizeHandles.clear();
265 }
266 d->selected.append(w);
268 emitActionSignals(false);
269
270 // WidgetStack and TabWidget pages widgets shouldn't have resize handles, but their parent
271 if(!FormManager::self()->isTopLevel(w) && w->parentWidget() && w->parentWidget()->isA("TQWidgetStack"))
272 {
273 w = w->parentWidget();
274 if(w->parentWidget() && w->parentWidget()->inherits("TQTabWidget"))
275 w = w->parentWidget();
276 }
277
278 if(w && w != widget())
279 d->resizeHandles.insert(w->name(), new ResizeHandleSet(w, this));
280}
281
284{
285 return d->resizeHandles[w->name()];
286}
287
288void
290{
291 d->selected.remove(w);
292 d->resizeHandles.remove(w->name());
293}
294
295void
300
301void
302Form::clearSelection()
303{
304 d->selected.clear();
305 d->resizeHandles.clear();
306 emit selectionChanged(0, false);
307 emitActionSignals(false);
308}
309
310void
312{
313 // Update menu and toolbar items
314 if(d->selected.count() > 1)
315 FormManager::self()->emitWidgetSelected(this, true);
316 else if(d->selected.first() != widget())
317 FormManager::self()->emitWidgetSelected(this, false);
318 else
319 FormManager::self()->emitFormWidgetSelected(this);
320
321 if(!withUndoAction)
322 return;
323
324 TDEAction *undoAction = d->collection->action("edit_undo");
325 if(undoAction)
326 FormManager::self()->emitUndoEnabled(undoAction->isEnabled(), undoAction->text());
327
328 TDEAction *redoAction = d->collection->action("edit_redo");
329 if(redoAction)
330 FormManager::self()->emitRedoEnabled(redoAction->isEnabled(), redoAction->text());
331}
332
333void
335{
336 emit selectionChanged(selectedWidgets()->first(), false);
337// for(TQWidget *w = selectedWidgets()->next(); w; w = selectedWidgets()->next())
338// emit selectionChanged(selectedWidgets()->first(), true);
339 for (WidgetListIterator it(*selectedWidgets()); it.current(); ++it)
340 emit selectionChanged(it.current(), true);
341}
342
344void
346{
347// clearSelection();
348 d->selected.clear();
349 d->resizeHandles.setAutoDelete(false);
350 d->resizeHandles.clear();
351 d->resizeHandles.setAutoDelete(true);
352// emit selectionChanged(0, false);
353// emitActionSignals(false);
354
356 //delete this;
357 deleteLater();
358}
359
360void
361Form::changeName(const TQCString &oldname, const TQCString &newname)
362{
363 if(oldname == newname)
364 return;
365 if(!d->topTree->rename(oldname, newname)) // rename failed
366 {
367 KMessageBox::sorry(widget()->topLevelWidget(),
368 i18n("Renaming widget \"%1\" to \"%2\" failed.").arg(TQString(oldname)).arg(TQString(newname)));
369//moved to WidgetPropertySet::slotChangeProperty()
370// KMessageBox::sorry(widget()->topLevelWidget(),
371// i18n("A widget with this name already exists. "
372// "Please choose another name or rename existing widget."));
373 kdDebug() << "Form::changeName() : ERROR : A widget named " << newname << " already exists" << endl;
374 FormManager::self()->propertySet()->property("name") = TQVariant(oldname);
375 }
376 else
377 {
378 d->connBuffer->fixName(oldname, newname);
379 ResizeHandleSet *temp = d->resizeHandles.take(oldname);
380 d->resizeHandles.insert(newname, temp);
381 }
382}
383
384void
390
391void
393{
394 d->tabstops.remove(item);
395 if(d->connBuffer)
396 d->connBuffer->removeAllConnectionsForWidget(item->name());
397 emit childRemoved(item);
398}
399
400void
401Form::addCommand(KCommand *command, bool execute)
402{
403 emit FormManager::self()->dirty(this, true);
404 d->dirty = true;
405 d->history->addCommand(command, execute);
406 if(!execute) // simulate command to activate 'undo' menu
408}
409
410void
412{
413 d->history->clear();
414 FormManager::self()->emitUndoEnabled(false, TQString());
415 FormManager::self()->emitRedoEnabled(false, TQString());
416}
417
418void
420{
421 emit FormManager::self()->dirty(this, true);
422 d->dirty = true;
423 // because actions text is changed after the commandExecuted() signal is emitted
424 TQTimer::singleShot(10, this, TQ_SLOT(emitUndoEnabled()));
425 TQTimer::singleShot(10, this, TQ_SLOT(emitRedoEnabled()));
426}
427
428void
429Form::emitUndoEnabled()
430{
431 TDEAction *undoAction = d->collection->action("edit_undo");
432 if(undoAction)
433 FormManager::self()->emitUndoEnabled(undoAction->isEnabled(), undoAction->text());
434}
435
436void
437Form::emitRedoEnabled()
438{
439 TDEAction *redoAction = d->collection->action("edit_redo");
440 if(redoAction)
441 FormManager::self()->emitRedoEnabled(redoAction->isEnabled(), redoAction->text());
442}
443
444void
446{
447 emit FormManager::self()->dirty(this, false);
448 d->dirty = false;
449}
450
451
453
454void
456{
457 TQWidget *w = it->widget();
458 if(!w)
459 return;
460 if(!(w->focusPolicy() & TQWidget::TabFocus))
461 {
462 TQObjectList clo = w->childrenListObject();
463 if (clo.isEmpty())
464 return;
465 // For composed widgets, we check if one of the child can have focus
466 for(TQObjectListIterator chIt(clo); chIt.current(); ++chIt) {
467 if(chIt.current()->isWidgetType()) {//TQWidget::TabFocus flag will be checked later!
468 if(d->tabstops.findRef(it) == -1) {
469 d->tabstops.append(it);
470 return;
471 }
472 }
473 }
474 }
475 else if(d->tabstops.findRef(it) == -1) // not yet in the list
476 d->tabstops.append(it);
477}
478
479void
481{
482 for (ObjectTreeListIterator it(d->tabstops);it.current();) {
483 if(!(it.current()->widget()->focusPolicy() & TQWidget::TabFocus)) {
484 kexidbg << "Form::updateTabStopsOrder(): widget removed because has no TabFocus: " << it.current()->widget()->name() << endl;
485 d->tabstops.remove( it.current() );
486 }
487 else
488 ++it;
489 }
490}
491
493void collectContainers(ObjectTreeItem* item, TQPtrDict<char>& containers)
494{
495 if (!item->container())
496 return;
497 if (!containers[ item->container() ]) {
498 kdDebug() << "collectContainers() " << item->container()->objectTree()->className()
499 << " " << item->container()->objectTree()->name() << endl;
500 containers.insert( item->container(), (const char *)1 );
501 }
502 for (ObjectTreeListIterator it(*item->children()); it.current(); ++it)
503 collectContainers(it.current(), containers);
504}
505
506void
508{
511
512 // 1. Collect all the containers, as we'll be sorting widgets groupped by containers
513 TQPtrDict<char> containers;
514
515 collectContainers( toplevelContainer()->objectTree(), containers );
516
517 foreach_list(ObjectTreeListIterator, it, d->tabstops) {
518 if(it.current()->widget()) {
519 kdDebug() << "Form::autoAssignTabStops() widget to sort: " << it.current()->widget() << endl;
520 list.append(it.current()->widget());
521 }
522 }
523
524 list.sort();
525 foreach_list(TQPtrListIterator<TQWidget>, iter, list)
526 kdDebug() << iter.current()->className() << " " << iter.current()->name() << endl;
527
528 d->tabstops.clear();
529
532 foreach_list(WidgetListIterator, it, list) {
533 TQWidget *w = it.current();
534 hlist.append(w);
535
536 ++it;
537 TQWidget *nextw = it.current();
538 TQObject *page_w = 0;
540 while (nextw) {
541 if (KexiUtils::hasParent(w, nextw)) // do not group (sort) widgets where on is a child of another
542 break;
543 if (nextw->y() >= (w->y() + 20))
544 break;
545 if (tab_w) {
546 TQObject *page_nextw = 0;
548 if (tab_w == tab_nextw) {
549 if (page_w != page_nextw) // 'nextw' widget within different tab page
550 break;
551 }
552 }
553 hlist.append(nextw);
554 ++it;
555 nextw = it.current();
556 }
557 hlist.sort();
558
559 for(WidgetListIterator it2(hlist); it2.current() != 0; ++it2) {
560 ObjectTreeItem *tree = d->topTree->lookup(it2.current()->name());
561 if(tree) {
562 kdDebug() << "Form::autoAssignTabStops() adding " << tree->name() << endl;
563 d->tabstops.append(tree);
564 }
565 }
566
567 --it;
568 hlist.clear();
569 }
570}
571
573{
574 return d->formatVersion;
575}
576
577void Form::setFormatVersion(uint ver)
578{
579 d->formatVersion = ver;
580}
582{
583 return d->originalFormatVersion;
584}
585
586void Form::setOriginalFormatVersion(uint ver)
587{
588 d->originalFormatVersion = ver;
589}
590
591void Form::setFormWidget(FormWidget* w)
592{
593 if (!d)
594 return;
595 d->formWidget = w;
596 if (!d->formWidget)
597 return;
598 d->formWidget->m_form = this;
599}
600
601#include "form.moc"
This class makes a container out of any TQWidget.
Definition container.h:74
ObjectTreeItem * objectTree() const
Definition container.h:97
void dirty(KFormDesigner::Form *form, bool isDirty=true)
static FormManager * self()
Access to FormManager singleton.
void deleteForm(Form *form)
WidgetPropertySet * propertySet() const
Base (virtual) class for all form widgets.
Definition form.h:54
uint originalFormatVersion() const
Definition form.cpp:581
void selectFormWidget()
Definition form.cpp:296
Form(WidgetLibrary *library, const char *name=0, bool designMode=true)
Definition form.cpp:91
void changeName(const TQCString &oldname, const TQCString &newname)
Definition form.cpp:361
void childAdded(ObjectTreeItem *it)
void destroying()
This signal emitted when Form is about to be destroyed.
void addCommand(KCommand *command, bool execute)
Definition form.cpp:401
void slotCommandExecuted()
Definition form.cpp:419
uint formatVersion() const
Definition form.cpp:572
ResizeHandleSet * resizeHandlesForWidget(TQWidget *w)
Definition form.cpp:283
void emitChildRemoved(ObjectTreeItem *item)
Definition form.cpp:392
void addWidgetToTabStops(ObjectTreeItem *it)
Definition form.cpp:455
void setSelectedWidget(TQWidget *selected, bool add=false, bool dontRaise=false, bool moreWillBeSelected=false)
Definition form.cpp:237
Container * toplevelContainer() const
Definition form.h:161
void emitSelectionSignals()
Definition form.cpp:334
void autoAssignTabStops()
Definition form.cpp:507
Container * parentContainer(TQWidget *w=0)
Definition form.cpp:196
ObjectTreeItem * commonParentContainer(WidgetList *wlist)
Definition form.cpp:171
WidgetList * selectedWidgets() const
Definition form.h:192
Container * activeContainer()
Definition form.cpp:151
void selectionChanged(TQWidget *w, bool add, bool moreWillBeSelected=false)
ObjectTree * objectTree() const
Definition form.h:167
bool designMode() const
Definition form.h:226
void updateTabStopsOrder()
Definition form.cpp:480
FormWidget * formWidget() const
Definition form.h:164
void clearCommandHistory()
Definition form.cpp:411
void emitChildAdded(ObjectTreeItem *item)
Definition form.cpp:385
void slotFormRestored()
Definition form.cpp:445
void emitActionSignals(bool withUndoAction=true)
Definition form.cpp:311
void setDesignMode(bool design)
Definition form.cpp:214
TQWidget * widget() const
Definition form.cpp:114
void childRemoved(ObjectTreeItem *it)
void unSelectWidget(TQWidget *w)
Definition form.cpp:289
void createToplevel(TQWidget *container, FormWidget *formWidget=0, const TQCString &classname="TQWidget")
Definition form.cpp:127
A helper for sorting widgets horizontally.
An item representing a widget Holds the properties of a widget (classname, name, parent,...
Definition objecttree.h:59
Container * container() const
Definition objecttree.h:76
Represents all the objects available within a form. This class holds ObjectTreeItem for each widget i...
Definition objecttree.h:140
a set of resize handles (for resizing widgets)
A tab widget providing information about height of the tab bar.
A helper for sorting widgets vertically.
This class searches for factories and provides TDEActions for widget creation.
A class that store pixmaps (by path or by name for KDE icons)
TQPtrList< TQWidget > WidgetList
A list of widget pointers.
TQDictIterator< ObjectTreeItem > ObjectTreeDictIterator
An iterator for ObjectTreeDict.
Definition objecttree.h:51
TQPtrListIterator< TQWidget > WidgetListIterator
An iterator for WidgetList.
KFORMEDITOR_EXPORT void removeChildrenFromList(WidgetList &list)
TQPtrListIterator< ObjectTreeItem > ObjectTreeListIterator
An iterator for ObjectTreeList.
Definition objecttree.h:45
type * findParent(TQObject *o, const char *className, TQObject *&prevPrev)
TQDict< ObjectTreeItem > ObjectTreeDict
A TQString-based disctionary of ObjectTreeItem pointers.
Definition objecttree.h:48
bool hasParent(TQObject *par, TQObject *o)