kexi

widgetpropertyset.cpp
1/* This file is part of the KDE project
2 Copyright (C) 2004 Cedric Pasteur <cedric.pasteur@free.fr>
3 Copyright (C) 2004-2006 Jaroslaw Staniek <js@iidea.pl>
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB. If not, write to
17 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19*/
20#include "widgetpropertyset.h"
21
22#include <tqstringlist.h>
23#include <tqstrlist.h>
24#include <tqmetaobject.h>
25#include <tqvariant.h>
26#include <tqevent.h>
27#include <tqlayout.h>
28#include <tqapplication.h>
29#include <tqeventloop.h>
30
31#include <tdelocale.h>
32#include <kdebug.h>
33#include <tdemessagebox.h>
34
35#include "objecttree.h"
36#include "form.h"
37#include "container.h"
38#include "formmanager.h"
39#include "widgetlibrary.h"
40#include "commands.h"
41#include "widgetwithsubpropertiesinterface.h"
42
43#include <kexiutils/utils.h>
44#include <kexiutils/identifier.h>
45
46using namespace KFormDesigner;
47
48namespace KFormDesigner {
49
51typedef TQValueList< TQGuardedPtr<TQWidget> > TQGuardedWidgetList;
52
54class WidgetPropertySetPrivate
55{
56 public:
57 WidgetPropertySetPrivate()
58 : lastCommand(0), lastGeoCommand(0),
59 isUndoing(false), slotPropertyChangedEnabled(true),
60 slotPropertyChanged_addCommandEnabled(true),
61 origActiveColors(0)
62 {}
63 ~WidgetPropertySetPrivate()
64 {
65 delete origActiveColors;
66 }
67
68 KoProperty::Set set;
69 // list of properties (not) to show in editor
70 TQStringList properties;
71 // list of widgets
72 TQGuardedWidgetList widgets;
73// FormManager *manager;
74
75 // used to update command's value when undoing
76 PropertyCommand *lastCommand;
77 GeometryPropertyCommand *lastGeoCommand;
78 bool isUndoing : 1;
79 bool slotPropertyChangedEnabled : 1;
80 bool slotPropertyChanged_addCommandEnabled : 1;
81
82 // helper to change color palette when switching 'enabled' property
83 TQColorGroup* origActiveColors;
84
85 // i18n stuff
86 TQMap<TQCString, TQString> propCaption;
87 TQMap<TQCString, TQString> propValCaption;
88};
89}
90
91WidgetPropertySet::WidgetPropertySet(TQObject *parent)
92 : TQObject(parent, "kfd_widgetPropertySet")
93{
94 d = new WidgetPropertySetPrivate();
95// d->manager = manager;
96
97 connect(&d->set, TQ_SIGNAL(propertyChanged(KoProperty::Set&, KoProperty::Property&)),
98 this, TQ_SLOT(slotPropertyChanged(KoProperty::Set&, KoProperty::Property&)));
99 connect(&d->set, TQ_SIGNAL(propertyReset(KoProperty::Set&, KoProperty::Property&)),
100 this, TQ_SLOT(slotPropertyReset(KoProperty::Set&, KoProperty::Property&)));
101
102 initPropertiesDescription();
103}
104
105WidgetPropertySet::~WidgetPropertySet()
106{
107 delete d;
108}
109
110/*FormManager*
111WidgetPropertySet::manager()
112{
113 return d->manager;
114}*/
115
116KoProperty::Property&
117WidgetPropertySet::operator[](const TQCString &name)
118{
119 return d->set[name];
120}
121
122KoProperty::Property&
123WidgetPropertySet::property(const TQCString &name)
124{
125 return d->set[name];
126}
127
128bool
129WidgetPropertySet::contains(const TQCString &property)
130{
131 return d->set.contains(property);
132}
133
134KoProperty::Set*
135WidgetPropertySet::set()
136{
137 return &(d->set);
138}
139
140void
141WidgetPropertySet::clearSet(bool dontSignalShowPropertySet)
142{
143 saveModifiedProperties();
144
145 if (!dontSignalShowPropertySet)
147 d->widgets.clear();
148 d->lastCommand = 0;
149 d->lastGeoCommand = 0;
150 d->properties.clear();
151 d->set.clear();
152
153 if(!d->widgets.isEmpty()) {
154 d->widgets.first()->removeEventFilter(this);
155 disconnect(d->widgets.first(), 0, this, 0);
156 }
157}
158
159void
160WidgetPropertySet::saveModifiedProperties()
161{
162 TQWidget * w = d->widgets.first();
163 if(!w || d->widgets.count() > 1 || !KFormDesigner::FormManager::self()->activeForm() || !KFormDesigner::FormManager::self()->activeForm()->objectTree())
164 return;
165 ObjectTreeItem *tree = KFormDesigner::FormManager::self()->activeForm()->objectTree()->lookup(w->name());
166 if(!tree)
167 return;
168
169 for(KoProperty::Set::Iterator it(d->set); it.current(); ++it) {
170 if(it.current()->isModified())
171 tree->addModifiedProperty(it.current()->name(), it.current()->oldValue());
172 }
173}
174
175void
176WidgetPropertySet::setUndoing(bool isUndoing)
177{
178 d->isUndoing = isUndoing;
179}
180
181bool
182WidgetPropertySet::isUndoing()
183{
184 return d->isUndoing;
185}
186
188
189void
190WidgetPropertySet::setSelectedWidget(TQWidget *w, bool add, bool forceReload, bool moreWillBeSelected)
191{
192 if(!w) {
193 clearSet();
194 return;
195 }
196
197 // don't add a widget twice
198 if(!forceReload && d->widgets.contains(TQGuardedPtr<TQWidget>(w))) {
199 kdWarning() << "WidgetPropertySet::setSelectedWidget() Widget is already selected" << endl;
200 return;
201 }
202 // if our list is empty,don't use add parameter value
203 if(d->widgets.count() == 0)
204 add = false;
205
206 TQCString prevProperty;
207 if(add)
208 addWidget(w);
209 else {
210 if (forceReload) {
212 prevProperty = d->set.prevSelection();
213 }
214 clearSet(true); //clear but do not reload to avoid blinking
215 d->widgets.append(TQGuardedPtr<TQWidget>(w));
216 createPropertiesForWidget(w);
217
218 w->installEventFilter(this);
219 connect(w, TQ_SIGNAL(destroyed()), this, TQ_SLOT(slotWidgetDestroyed()));
220 }
221
222 if (!moreWillBeSelected)
223 KFormDesigner::FormManager::self()->showPropertySet(this, true/*force*/, prevProperty);
224}
225
226void
227WidgetPropertySet::addWidget(TQWidget *w)
228{
229 d->widgets.append(TQGuardedPtr<TQWidget>(w));
230
231 // Reset some stuff
232 d->lastCommand = 0;
233 d->lastGeoCommand = 0;
234 d->properties.clear();
235
236 TQCString classname;
237 if(d->widgets.first()->className() == w->className())
238 classname = d->widgets.first()->className();
239
240 // show only properties shared by widget (properties chosen by factory)
241 bool isTopLevel = KFormDesigner::FormManager::self()->isTopLevel(w);
242
243 //WidgetWithSubpropertiesInterface* subpropIface = dynamic_cast<WidgetWithSubpropertiesInterface*>(w);
244// TQWidget *subwidget = isSubproperty ? subpropIface->subwidget() : w;
245
246 for(KoProperty::Set::Iterator it(d->set); it.current(); ++it) {
247 kdDebug() << it.currentKey() << endl;
248 if(!isPropertyVisible(it.currentKey(), isTopLevel, classname))
249 d->set[it.currentKey()].setVisible(false);
250 }
251
252 if (d->widgets.count()>=2) {
253 //second widget, update metainfo
254 d->set["this:className"].setValue("special:multiple");
255 d->set["this:classString"].setValue(
256 i18n("Multiple Widgets") + TQString(" (%1)").arg(d->widgets.count()) );
257 d->set["this:iconName"].setValue("multiple_obj");
258 //name doesn't make sense for now
259 d->set["name"].setValue("");
260 }
261}
262
263void
264WidgetPropertySet::createPropertiesForWidget(TQWidget *w)
265{
266 Form *form;
268 || !(form = KFormDesigner::FormManager::self()->activeForm())
269 || !KFormDesigner::FormManager::self()->activeForm()->objectTree())
270 {
271 kdWarning() << "WidgetPropertySet::createPropertiesForWidget() no manager or active form!!!" << endl;
272 return;
273 }
274 ObjectTreeItem *tree = form->objectTree()->lookup(w->name());
275 if(!tree)
276 return;
277
278 const TQStringVariantMap* modifiedProperties = tree->modifiedProperties();
279 TQStringVariantMapConstIterator modifiedPropertiesIt;
280 bool isTopLevel = KFormDesigner::FormManager::self()->isTopLevel(w);
281// int count = 0;
282 KoProperty::Property *newProp = 0;
283 WidgetInfo *winfo = form->library()->widgetInfoForClassName(w->className());
284 if (!winfo) {
285 kdWarning() << "WidgetPropertySet::createPropertiesForWidget() no widget info for class "
286 << w->className() << endl;
287 return;
288 }
289
290 TQStrList pList = w->metaObject()->propertyNames(true);
291 TQStrListIterator it(pList);
292
293 // add subproperties if available
294 WidgetWithSubpropertiesInterface* subpropIface = dynamic_cast<WidgetWithSubpropertiesInterface*>(w);
295 TQStrList tmpList; //used to allocate copy of names
296 if (subpropIface) {
297 TQValueList<TQCString> subproperies(
298 subpropIface->subproperies() );
299 foreach(TQValueListConstIterator<TQCString>, it, subproperies ) {
300 tmpList.append( *it );
301 pList.append( tmpList.last() );
302 kdDebug() << "Added subproperty: " << *it << endl;
303 }
304 }
305
306 // iterate over the property list, and create Property objects
307 for(; it.current() != 0; ++it) {
308 //kdDebug() << ">> " << it.current() << endl;
309 const TQMetaProperty *subMeta = // special case - subproperty
310 subpropIface ? subpropIface->findMetaSubproperty(it.current()) : 0;
311 const TQMetaProperty *meta = subMeta ? subMeta
312 : w->metaObject()->property( w->metaObject()->findProperty(*it, true), true);
313 if (!meta)
314 continue;
315 const char* propertyName = meta->name();
316 TQWidget *subwidget = subMeta/*subpropIface*/ ? subpropIface->subwidget() : w;
317 WidgetInfo *subwinfo = form->library()->widgetInfoForClassName(subwidget->className());
318// kdDebug() << "$$$ " << subwidget->className() << endl;
319
320 if(subwinfo && meta->designable(subwidget) && !d->set.contains(propertyName)) {
322 TQString desc( d->propCaption[meta->name()] );
324 if (desc.isEmpty()) //try to get property description from factory
325 desc = form->library()->propertyDescForName(subwinfo, propertyName);
326
327 modifiedPropertiesIt = modifiedProperties->find(propertyName);
328 const bool oldValueExists = modifiedPropertiesIt!=modifiedProperties->constEnd();
329
330 if(meta->isEnumType()) {
331 if(qstrcmp(propertyName, "alignment") == 0) {
332 createAlignProperty(meta, w, subwidget);
333 continue;
334 }
335
336 TQStringList keys = TQStringList::fromStrList( meta->enumKeys() );
337 newProp = new KoProperty::Property(propertyName, createValueList(subwinfo, keys),
338 /* assign current or older value */
339 meta->valueToKey(
340 oldValueExists ? modifiedPropertiesIt.data().toInt() : subwidget->property(propertyName).toInt() ),
341 desc, desc );
342 //now set current value, so the old one is stored as old
343 if (oldValueExists) {
344 newProp->setValue( meta->valueToKey( subwidget->property(propertyName).toInt() ) );
345 }
346 }
347 else {
348 newProp = new KoProperty::Property(propertyName,
349 /* assign current or older value */
350 oldValueExists ? TQVariant(modifiedPropertiesIt.data()) : TQVariant(subwidget->property(propertyName)),
351 desc, desc, subwinfo->customTypeForProperty(propertyName));
352 //now set current value, so the old one is stored as old
353 if (oldValueExists) {
354 newProp->setValue( subwidget->property(propertyName) );
355 }
356 }
357
358 d->set.addProperty(newProp);
359 if(!isPropertyVisible(propertyName, isTopLevel))
360 newProp->setVisible(false);
362 if(newProp->type() == 0) // invalid type == null pixmap ?
363 newProp->setType(KoProperty::Pixmap);
364 }
365
366// if(0==qstrcmp(propertyName, "name"))
367// (*this)["name"].setAutoSync(0); // name should be updated only when pressing Enter
368
369 // \todo js what does this mean? why do you use WidgetInfo and not WidgetLibrary
370 /*if (winfo) {
371 tristate autoSync = winfo->autoSyncForProperty( propertyName );
372 if (! ~autoSync)
373 d->set[propertyName].setAutoSync( autoSync );
374 }*/
375
376 // update the Property.oldValue() and isModified() using the value stored in the ObjectTreeItem
377 updatePropertyValue(tree, propertyName, meta);
378 }
379
380 (*this)["name"].setAutoSync(false); // name should be updated only when pressing Enter
381 (*this)["enabled"].setValue( TQVariant(tree->isEnabled()));
382
383 if (winfo) {
384 form->library()->setPropertyOptions(*this, *winfo, w);
385 d->set.addProperty( newProp = new KoProperty::Property("this:classString", winfo->name()) );
386 newProp->setVisible(false);
387 d->set.addProperty( newProp = new KoProperty::Property("this:iconName", winfo->pixmap()) );
388 newProp->setVisible(false);
389 }
390 d->set.addProperty( newProp = new KoProperty::Property("this:className", w->className()) );
391 newProp->setVisible(false);
392
405
406 if(KFormDesigner::FormManager::self()->activeForm() && tree->container()) // we are a container -> layout property
407 createLayoutProperty(tree);
408}
409
410void
411WidgetPropertySet::updatePropertyValue(ObjectTreeItem *tree, const char *property, const TQMetaProperty *meta)
412{
413 const char *propertyName = meta ? meta->name() : property;
414 if (!d->set.contains(propertyName))
415 return;
416 KoProperty::Property p( d->set[propertyName] );
417
419 TQStringVariantMap::ConstIterator it( tree->modifiedProperties()->find(propertyName) );
420 if (it != tree->modifiedProperties()->constEnd()) {
421 blockSignals(true);
422 if(meta && meta->isEnumType()) {
423 p.setValue( meta->valueToKey( it.data().toInt() ), false );
424 }
425 else {
426 p.setValue(it.data(), false );
427 }
428 p.setValue(p.value(), true);
429 blockSignals(false);
430 }
431}
432
433bool
434WidgetPropertySet::isPropertyVisible(const TQCString &property, bool isTopLevel, const TQCString &classname)
435{
436 const bool multiple = d->widgets.count() >= 2;
437 if(multiple && classname.isEmpty())
438 return false;
439/* moved to WidgetLibrary::isPropertyVisible()
440 if(d->widgets.count() < 2)
441 {
442 if(d->properties.isEmpty() && !isTopLevel)
443 d->properties << "caption" << "icon" << "sizeIncrement" << "iconText";
444 // don't show these properties for a non-toplevel widget
445
446 if(! (d->properties.grep(property)).isEmpty() )
447 return false;
448 }
449 else
450 {
451 if(classname.isEmpty())
452 return false;
453
454 if(d->properties.isEmpty()) {
455 d->properties << "font" << "paletteBackgroundColor" << "enabled" << "paletteForegroundColor"
456 << "cursor" << "paletteBackgroundPixmap";
457 } // properties always shown in multiple mode
458 if(! (d->properties.grep(property)).isEmpty() )
459 return true;
460 }
461*/
462
463// return KFormDesigner::FormManager::self()->lib()->isPropertyVisible(d->widgets.first()->className(), d->widgets.first(),
464 TQWidget *w = d->widgets.first();
465 WidgetWithSubpropertiesInterface* subpropIface = dynamic_cast<WidgetWithSubpropertiesInterface*>(w);
466 TQWidget *subwidget;
467 if (subpropIface && subpropIface->findMetaSubproperty(property)) // special case - subproperty
468 subwidget = subpropIface->subwidget();
469 else
470 subwidget = w;
471
472 return KFormDesigner::FormManager::self()->activeForm()->library()->isPropertyVisible(
473 subwidget->className(), subwidget, property, multiple, isTopLevel);
474}
475
477
478void
479WidgetPropertySet::slotPropertyChanged(KoProperty::Set& set, KoProperty::Property& p)
480{
481 Q_UNUSED( set );
482
483 if(!d->slotPropertyChangedEnabled || !KFormDesigner::FormManager::self() || !KFormDesigner::FormManager::self()->activeForm()
485 return;
486
487 TQCString property = p.name();
488 if (0==property.find("this:"))
489 return; //starts with magical prefix: it's a "meta" prop.
490
491 TQVariant value = p.value();
492
493 // check if the name is valid (ie is correct identifier) and there is no name conflict
494 if(property == "name") {
495 if(d->widgets.count()!=1)
496 return;
497 if(!isNameValid(value.toString()))
498 return;
499 }
500 // a widget with a background pixmap should have its own origin
501 else if(property == "paletteBackgroundPixmap") {
502 d->set["backgroundOrigin"] = "WidgetOrigin";
503 //else if(property == "signals")
504 // return;
505 // special types of properties handled separately
506 } else if((property == "hAlign") || (property == "vAlign") || (property == "wordbreak")) {
507 saveAlignProperty(property);
508 return;
509 }
510 else if((property == "layout") || (property == "layoutMargin") || (property == "layoutSpacing")) {
511 saveLayoutProperty(property, value);
512 return;
513 }
514 // we cannot really disable the widget, we just change its color palette
515 else if(property == "enabled") {
516 saveEnabledProperty(value.toBool());
517 return;
518 }
519
520 // make sure we are not already undoing -> avoid recursion
521 if(d->isUndoing && !KFormDesigner::FormManager::self()->isRedoing())
522 return;
523
524 const bool alterLastCommand = d->lastCommand && d->lastCommand->property() == property;
525
526 if(d->widgets.count() == 1) // one widget selected
527 {
528 // If the last command is the same, we just change its value
529 if(alterLastCommand && !KFormDesigner::FormManager::self()->isRedoing())
530 d->lastCommand->setValue(value);
531 else {
532// if(m_widgets.first() && ((m_widgets.first() != m_manager->activeForm()->widget()) || (property != "geometry"))) {
533 if (d->slotPropertyChanged_addCommandEnabled && !KFormDesigner::FormManager::self()->isRedoing()) {
534 d->lastCommand = new PropertyCommand(this, d->widgets.first()->name(),
535 d->widgets.first()->property(property), value, property);
536 KFormDesigner::FormManager::self()->activeForm()->addCommand(d->lastCommand, false);
537 }
538
539 // If the property is changed, we add it in ObjectTreeItem modifProp
540 ObjectTreeItem *tree = KFormDesigner::FormManager::self()->activeForm()->objectTree()->lookup(d->widgets.first()->name());
541 if (tree && p.isModified())
542 tree->addModifiedProperty(property, d->widgets.first()->property(property));
543 }
544
545 if(property == "name")
546 emit widgetNameChanged(d->widgets.first()->name(), p.value().toCString());
547 d->widgets.first()->setProperty(property, value);
548 emitWidgetPropertyChanged(d->widgets.first(), property, value);
549 }
550 else
551 {
552 if(alterLastCommand && !KFormDesigner::FormManager::self()->isRedoing())
553 d->lastCommand->setValue(value);
554 else {
555 if (d->slotPropertyChanged_addCommandEnabled && !KFormDesigner::FormManager::self()->isRedoing()) {
556 // We store old values for each widget
557 TQMap<TQCString, TQVariant> list;
558 // for(TQWidget *w = d->widgets.first(); w; w = d->widgets.next())
559 foreach(TQGuardedWidgetList::ConstIterator, it, d->widgets)
560 list.insert((*it)->name(), (*it)->property(property));
561
562 d->lastCommand = new PropertyCommand(this, list, value, property);
563 KFormDesigner::FormManager::self()->activeForm()->addCommand(d->lastCommand, false);
564 }
565 }
566
567// for(TQWidget *w = d->widgets.first(); w; w = d->widgets.next())
568 foreach(TQGuardedWidgetList::ConstIterator, it, d->widgets) {
569 if (!alterLastCommand) {
570 ObjectTreeItem *tree = KFormDesigner::FormManager::self()->activeForm()->objectTree()
571 ->lookup((*it)->name());
572 if(tree && p.isModified())
573 tree->addModifiedProperty(property, (*it)->property(property));
574 }
575 (*it)->setProperty(property, value);
576 emitWidgetPropertyChanged((*it), property, value);
577 }
578 }
579}
580
581void WidgetPropertySet::emitWidgetPropertyChanged(TQWidget *w, const TQCString& property, const TQVariant& value)
582{
583 emit widgetPropertyChanged(w, property, value);
584
586 if (form && form->library()->propertySetShouldBeReloadedAfterPropertyChange( w->className(), w, property)) {
587 //setSelectedWidget(0, false);
588 tqApp->eventLoop()->processEvents(TQEventLoop::AllEvents); //be sure events related to editors are consumed
589 setSelectedWidget(w, false, /*forceReload*/true);
590 tqApp->eventLoop()->processEvents(TQEventLoop::AllEvents); //be sure events related to editors are consumed
591 //KFormDesigner::FormManager::self()->showPropertySet(this, true/*forceReload*/);
592 }
593}
594
595void
596WidgetPropertySet::createPropertyCommandsInDesignMode(TQWidget* widget,
597 const TQMap<TQCString, TQVariant> &propValues, CommandGroup *group, bool addToActiveForm,
598 bool execFlagForSubCommands)
599{
600 if (!widget || propValues.isEmpty())
601 return;
602
603 //is this widget selected? (if so, use property system)
604 const bool widgetIsSelected = KFormDesigner::FormManager::self()->activeForm()->selectedWidget() == widget;
605
606 d->slotPropertyChanged_addCommandEnabled = false;
607 TQMap<TQCString, TQVariant>::ConstIterator endIt = propValues.constEnd();
608// CommandGroup *group = new CommandGroup(commandName);
609 for(TQMap<TQCString, TQVariant>::ConstIterator it = propValues.constBegin(); it != endIt; ++it)
610 {
611 if (!d->set.contains(it.key())) {
612 kdWarning() << "WidgetPropertySet::createPropertyCommandsInDesignMode(): \"" <<it.key()<<"\" property not found"<<endl;
613 continue;
614 }
615 PropertyCommand *subCommand = new PropertyCommand(this, widget->name(),
616 widget->property(it.key()), it.data(), it.key());
617 group->addCommand( subCommand, execFlagForSubCommands);
618 if (widgetIsSelected) {
619 d->set[it.key()].setValue(it.data());
620 }
621 else {
622 WidgetWithSubpropertiesInterface* subpropIface = dynamic_cast<WidgetWithSubpropertiesInterface*>(widget);
623 TQWidget *subwidget = (subpropIface && subpropIface->subwidget()) ? subpropIface->subwidget() : widget;
624 if (-1 != subwidget->metaObject()->findProperty(it.key(), true) && subwidget->property(it.key())!=it.data()) {
625 ObjectTreeItem *tree = KFormDesigner::FormManager::self()->activeForm()->objectTree()->lookup(widget->name());
626 if (tree)
627 tree->addModifiedProperty(it.key(), subwidget->property(it.key()));
628 subwidget->setProperty(it.key(), it.data());
629 emit widgetPropertyChanged(widget, it.key(), it.data());
630 }
631 }
632 }
633 d->lastCommand = 0;
634 if (addToActiveForm)
635 KFormDesigner::FormManager::self()->activeForm()->addCommand(group, false/*no exec*/);
636 d->slotPropertyChanged_addCommandEnabled = true;
637// }
638}
639
641void
642WidgetPropertySet::saveEnabledProperty(bool value)
643{
644// for(TQWidget *w = d->widgets.first(); w; w = d->widgets.next()) {
645 foreach(TQGuardedWidgetList::ConstIterator, it, d->widgets) {
646 ObjectTreeItem *tree = KFormDesigner::FormManager::self()->activeForm()->objectTree()
647 ->lookup((*it)->name());
648 if(tree->isEnabled() == value)
649 continue;
650
651 TQPalette p( (*it)->palette() );
652 if (!d->origActiveColors)
653 d->origActiveColors = new TQColorGroup( p.active() );
654 if (value) {
655 if (d->origActiveColors)
656 p.setActive( *d->origActiveColors ); //revert
657 }
658 else {
659 TQColorGroup cg = p.disabled();
660 //also make base color a bit disabled-like
661 cg.setColor(TQColorGroup::Base, cg.color(TQColorGroup::Background));
662 p.setActive(cg);
663 }
664 (*it)->setPalette(p);
665
666 tree->setEnabled(value);
667 emit widgetPropertyChanged((*it), "enabled", TQVariant(value));
668 }
669}
670
671bool
672WidgetPropertySet::isNameValid(const TQString &name)
673{
675 TQWidget *w = d->widgets.first();
676 //also update widget's name in TQObject member
677 if (!KexiUtils::isIdentifier(name)) {
678 KMessageBox::sorry(KFormDesigner::FormManager::self()->activeForm()->widget(),
679 i18n("Could not rename widget \"%1\" to \"%2\" because "
680 "\"%3\" is not a valid name (identifier) for a widget.\n")
681 .arg(w->name()).arg(name).arg(name));
682 d->slotPropertyChangedEnabled = false;
683 d->set["name"].resetValue();
684 d->slotPropertyChangedEnabled = true;
685 return false;
686 }
687
688 if (KFormDesigner::FormManager::self()->activeForm()->objectTree()->lookup(name)) {
689 KMessageBox::sorry( KFormDesigner::FormManager::self()->activeForm()->widget(),
690 i18n("Could not rename widget \"%1\" to \"%2\" "
691 "because a widget with the name \"%3\" already exists.\n")
692 .arg(w->name()).arg(name).arg(name));
693 d->slotPropertyChangedEnabled = false;
694 d->set["name"].resetValue();
695 d->slotPropertyChangedEnabled = true;
696 return false;
697 }
698
699 return true; //ie name is correct
700}
701
702void
703WidgetPropertySet::slotPropertyReset(KoProperty::Set& set, KoProperty::Property& property)
704{
705 Q_UNUSED( set );
706
707 if(d->widgets.count() < 2)
708 return;
709
710 // We use the old value in modifProp for each widget
711// for(TQWidget *w = d->widgets.first(); w; w = d->widgets.next()) {
712 foreach(TQGuardedWidgetList::ConstIterator, it, d->widgets) {
713 ObjectTreeItem *tree = KFormDesigner::FormManager::self()->activeForm()->objectTree()->lookup((*it)->name());
714 if(tree->modifiedProperties()->contains(property.name()))
715 (*it)->setProperty(property.name(), tree->modifiedProperties()->find(property.name()).data());
716 }
717}
718
719void
720WidgetPropertySet::slotWidgetDestroyed()
721{
722// if(d->widgets.contains(TQGuardedPtr<const TQWidget>( dynamic_cast<const TQWidget*>(sender()) ))) {
723 //only clear this set if it contains the destroyed widget
724 foreach(TQGuardedWidgetList::ConstIterator, it, d->widgets) {
725 if (dynamic_cast<const TQWidget*>(sender()) == *it) {
726 clearSet();
727 break;
728 }
729 }
730}
731
732bool
733WidgetPropertySet::eventFilter(TQObject *o, TQEvent *ev)
734{
735 if(d->widgets.count() > 0 && o == d->widgets.first() && d->widgets.count() < 2)
736 {
737 if((ev->type() == TQEvent::Resize) || (ev->type() == TQEvent::Move)) {
738 if(!d->set.contains("geometry"))
739 return false;
740 if(d->set["geometry"].value() == o->property("geometry")) // to avoid infinite recursion
741 return false;
742
743 d->set["geometry"] = static_cast<TQWidget*>(o)->geometry();
744 }
745 }
746 else if(d->widgets.count() > 1 && ev->type() == TQEvent::Move) // the widget is being moved, we update the property
747 {
748 if(d->isUndoing)
749 return false;
750
751 if(d->lastGeoCommand)
752 d->lastGeoCommand->setPos(static_cast<TQMoveEvent*>(ev)->pos());
753 else {
754 TQStringList list;
755 foreach(TQGuardedWidgetList::ConstIterator, it, d->widgets)
756 list.append((*it)->name());
757
758 d->lastGeoCommand = new GeometryPropertyCommand(this, list, static_cast<TQMoveEvent*>(ev)->oldPos());
759 if (KFormDesigner::FormManager::self()->activeForm())
760 KFormDesigner::FormManager::self()->activeForm()->addCommand(d->lastGeoCommand, false);
761 }
762 }
763
764 return false;
765}
766
767// Alignment-related functions /////////////////////////////
768
769void
770WidgetPropertySet::createAlignProperty(const TQMetaProperty *meta, TQWidget *widget, TQWidget *subwidget)
771{
772 if (!KFormDesigner::FormManager::self()->activeForm()
773|| !KFormDesigner::FormManager::self()->activeForm()->objectTree())
774 return;
775
776 TQStringList list;
777 TQString value;
778 const int alignment = subwidget->property("alignment").toInt();
779 const TQStringList keys( TQStringList::fromStrList( meta->valueToKeys(alignment) ) );
780
781 TQStrList *enumKeys = new TQStrList(meta->enumKeys());
782 const TQStringList possibleValues( TQStringList::fromStrList(*enumKeys) );
783 delete enumKeys;
784
785 ObjectTreeItem *tree = KFormDesigner::FormManager::self()->activeForm()->objectTree()->lookup(widget->name());
786 bool isTopLevel = KFormDesigner::FormManager::self()->isTopLevel(widget);
787
788 if(possibleValues.find("AlignHCenter")!=possibleValues.constEnd()) {
789 // Create the horizontal alignment property
790 if(keys.find("AlignHCenter")!=keys.constEnd() || keys.find("AlignCenter")!=keys.constEnd())
791 value = "AlignHCenter";
792 else if(keys.find("AlignRight")!=keys.constEnd())
793 value = "AlignRight";
794 else if(keys.find("AlignLeft")!=keys.constEnd())
795 value = "AlignLeft";
796 else if(keys.find("AlignJustify")!=keys.constEnd())
797 value = "AlignJustify";
798 else
799 value = "AlignAuto";
800
801 list << "AlignAuto" << "AlignLeft" << "AlignRight" << "AlignHCenter" << "AlignJustify";
802 KoProperty::Property *p = new KoProperty::Property("hAlign", createValueList(0, list), value,
803 i18n("Translators: please keep this string short (less than 20 chars)", "Hor. Alignment"),
804 i18n("Horizontal Alignment"));
805 d->set.addProperty(p);
806 if(!isPropertyVisible(p->name(), isTopLevel)) {
807 p->setVisible(false);
808 }
809 updatePropertyValue(tree, "hAlign");
810 list.clear();
811 }
812
813 if(possibleValues.find("AlignTop")!=possibleValues.constEnd())
814 {
815 // Create the ver alignment property
816 if(keys.find("AlignTop")!=keys.constEnd())
817 value = "AlignTop";
818 else if(keys.find("AlignBottom")!=keys.constEnd())
819 value = "AlignBottom";
820 else
821 value = "AlignVCenter";
822
823 list << "AlignTop" << "AlignVCenter" << "AlignBottom";
824 KoProperty::Property *p = new KoProperty::Property("vAlign", createValueList(0, list), value,
825 i18n("Translators: please keep this string short (less than 20 chars)", "Ver. Alignment"),
826 i18n("Vertical Alignment"));
827 d->set.addProperty(p);
828 if(!isPropertyVisible(p->name(), isTopLevel)) {
829 p->setVisible(false);
830 }
831 updatePropertyValue(tree, "vAlign");
832 }
833
834 if(possibleValues.find("WordBreak")!=possibleValues.constEnd()
835// && isPropertyVisible("wordbreak", false, subwidget->className())
836// && !subWidget->inherits("TQLineEdit") /* TQLineEdit doesn't support 'word break' is this generic enough?*/
837 ) {
838 // Create the wordbreak property
839 KoProperty::Property *p = new KoProperty::Property("wordbreak",
840 TQVariant(alignment & TQt::WordBreak), i18n("Word Break"), i18n("Word Break") );
841 d->set.addProperty(p);
842 updatePropertyValue(tree, "wordbreak");
843 if (!KFormDesigner::FormManager::self()->activeForm()->library()->isPropertyVisible(
844 subwidget->className(), subwidget, p->name(), false/*multiple*/, isTopLevel))
845 {
846 p->setVisible(false);
847 }
848 }
849}
850
851void
852WidgetPropertySet::saveAlignProperty(const TQString &property)
853{
854 if (!KFormDesigner::FormManager::self()->activeForm())
855 return;
856
857 TQStrList list;
858 if( d->set.contains("hAlign") )
859 list.append( d->set["hAlign"].value().toCString() );
860 if( d->set.contains("vAlign") )
861 list.append( d->set["vAlign"].value().toCString() );
862 if( d->set.contains("wordbreak") && d->set["wordbreak"].value().toBool() )
863 list.append("WordBreak");
864
865 WidgetWithSubpropertiesInterface* subpropIface = dynamic_cast<WidgetWithSubpropertiesInterface*>(
866 (TQWidget*)d->widgets.first() );
867 TQWidget *subwidget = (subpropIface && subpropIface->subwidget()) ? subpropIface->subwidget() : (TQWidget*)d->widgets.first();
868 int count = subwidget->metaObject()->findProperty("alignment", true);
869 const TQMetaProperty *meta = subwidget->metaObject()->property(count, true);
870 subwidget->setProperty("alignment", meta->keysToValue(list));
871
872 ObjectTreeItem *tree = KFormDesigner::FormManager::self()->activeForm()->objectTree()->lookup(
873 d->widgets.first()->name() );
874 if(tree && d->set[property.latin1()].isModified())
875 tree->addModifiedProperty(property.latin1(), d->set[property.latin1()].oldValue());
876
877 if(d->isUndoing)
878 return;
879
880 if(d->lastCommand && d->lastCommand->property() == "alignment")
881 d->lastCommand->setValue(meta->keysToValue(list));
882 else {
883 d->lastCommand = new PropertyCommand(this, d->widgets.first()->name(),
884 subwidget->property("alignment"), meta->keysToValue(list), "alignment");
885 KFormDesigner::FormManager::self()->activeForm()->addCommand(d->lastCommand, false);
886 }
887}
888
889// Layout-related functions //////////////////////////
890
891void
892WidgetPropertySet::createLayoutProperty(ObjectTreeItem *item)
893{
894 Container *container = item->container();
895 if (!container || !KFormDesigner::FormManager::self()->activeForm() ||
896 !KFormDesigner::FormManager::self()->activeForm()->objectTree() || !container->widget())
897 return;
898 // special containers have no 'layout' property, as it should not be changed
899 TQCString className = container->widget()->className();
900 if((className == "HBox") || (className == "VBox") || (className == "Grid"))
901 return;
902
903 TQStringList list;
904 TQString value = Container::layoutTypeToString(container->layoutType());
905
906 list << "NoLayout" << "HBox" << "VBox" << "Grid" << "HFlow" << "VFlow";
907
908 KoProperty::Property *p = new KoProperty::Property("layout", createValueList(0, list), value,
909 i18n("Container's Layout"), i18n("Container's Layout"));
910 p->setVisible( container->form()->library()->advancedPropertiesVisible() );
911 d->set.addProperty(p);
912
913 updatePropertyValue(item, "layout");
914
915 p = new KoProperty::Property("layoutMargin", container->layoutMargin(), i18n("Layout Margin"), i18n("Layout Margin"));
916 d->set.addProperty(p);
917 updatePropertyValue(item, "layoutMargin");
918 if(container->layoutType() == Container::NoLayout)
919 p->setVisible(false);
920
921 p = new KoProperty::Property("layoutSpacing", container->layoutSpacing(),
922 i18n("Layout Spacing"), i18n("Layout Spacing"));
923 d->set.addProperty(p);
924 updatePropertyValue(item, "layoutSpacing");
925 if(container->layoutType() == Container::NoLayout)
926 p->setVisible(false);
927
928}
929
930void
931WidgetPropertySet::saveLayoutProperty(const TQString &prop, const TQVariant &value)
932{
933 Container *container=0;
934 if(!KFormDesigner::FormManager::self()->activeForm() || !KFormDesigner::FormManager::self()->activeForm()->objectTree())
935 return;
936 ObjectTreeItem *item = KFormDesigner::FormManager::self()->activeForm()->objectTree()->lookup(d->widgets.first()->name());
937 if(!item)
938 return;
939 container = item->container();
940
941 if(prop == "layout") {
942 Container::LayoutType type = Container::stringToLayoutType(value.toString());
943
944 if(d->lastCommand && d->lastCommand->property() == "layout" && !d->isUndoing)
945 d->lastCommand->setValue(value);
946 else if(!d->isUndoing) {
947 d->lastCommand = new LayoutPropertyCommand(this, d->widgets.first()->name(),
948 d->set["layout"].oldValue(), value);
949 KFormDesigner::FormManager::self()->activeForm()->addCommand(d->lastCommand, false);
950 }
951
952 container->setLayout(type);
953 bool show = (type != Container::NoLayout);
954 if(show != d->set["layoutMargin"].isVisible()) {
955 d->set["layoutMargin"].setVisible(show);
956 d->set["layoutSpacing"].setVisible(show);
958 }
959 return;
960 }
961
962 if(prop == "layoutMargin" && container->layout()) {
963 container->setLayoutMargin(value.toInt());
964 container->layout()->setMargin(value.toInt());
965 }
966 else if(prop == "layoutSpacing" && container->layout()) {
967 container->setLayoutSpacing(value.toInt());
968 container->layout()->setSpacing(value.toInt());
969 }
970
971 ObjectTreeItem *tree = KFormDesigner::FormManager::self()->activeForm()->objectTree()->lookup(d->widgets.first()->name());
972 if(tree && d->set[ prop.latin1() ].isModified())
973 tree->addModifiedProperty(prop.latin1(), d->set[prop.latin1()].oldValue());
974
975 if(d->isUndoing)
976 return;
977
978 if(d->lastCommand && (TQString(d->lastCommand->property()) == prop))
979 d->lastCommand->setValue(value);
980 else {
981 d->lastCommand = new PropertyCommand(this, d->widgets.first()->name(),
982 d->set[ prop.latin1() ].oldValue(), value, prop.latin1());
983 KFormDesigner::FormManager::self()->activeForm()->addCommand(d->lastCommand, false);
984 }
985}
986
987
988
990
991void
992WidgetPropertySet::initPropertiesDescription()
993{
996 d->propCaption["name"] = i18n("Name");
997 d->propCaption["caption"] = i18n("Caption");
998 d->propCaption["text"] = i18n("Text");
999 d->propCaption["paletteBackgroundPixmap"] = i18n("Background Pixmap");
1000 d->propCaption["enabled"] = i18n("Enabled");
1001 d->propCaption["geometry"] = i18n("Geometry");
1002 d->propCaption["sizePolicy"] = i18n("Size Policy");
1003 d->propCaption["minimumSize"] = i18n("Minimum Size");
1004 d->propCaption["maximumSize"] = i18n("Maximum Size");
1005 d->propCaption["font"] = i18n("Font");
1006 d->propCaption["cursor"] = i18n("Cursor");
1007 d->propCaption["paletteForegroundColor"] = i18n("Foreground Color");
1008 d->propCaption["paletteBackgroundColor"] = i18n("Background Color");
1009 d->propCaption["focusPolicy"] = i18n("Focus Policy");
1010 d->propCaption["margin"] = i18n("Margin");
1011 d->propCaption["readOnly"] = i18n("Read Only");
1012 //any TQFrame
1013 d->propCaption["frame"] = i18n("Frame");
1014 d->propCaption["lineWidth"] = i18n("Frame Width");
1015 d->propCaption["midLineWidth"] = i18n("Mid Frame Width");
1016 d->propCaption["frameShape"] = i18n("Frame Shape");
1017 d->propCaption["frameShadow"] = i18n("Frame Shadow");
1018 //any TQScrollbar
1019 d->propCaption["vScrollBarMode"] = i18n("Vertical ScrollBar");
1020 d->propCaption["hScrollBarMode"] = i18n("Horizontal ScrollBar");
1021
1022 d->propValCaption["NoBackground"] = i18n("No Background");
1023 d->propValCaption["PaletteForeground"] = i18n("Palette Foreground");
1024 d->propValCaption["AutoText"] = i18n("Auto (HINT: for AutoText)", "Auto");
1025
1026 d->propValCaption["AlignAuto"] = i18n("Auto (HINT: for Align)", "Auto");
1027 d->propValCaption["AlignLeft"] = i18n("Left (HINT: for Align)", "Left");
1028 d->propValCaption["AlignRight"] = i18n("Right (HINT: for Align)", "Right");
1029 d->propValCaption["AlignHCenter"] = i18n("Center (HINT: for Align)", "Center");
1030 d->propValCaption["AlignJustify"] = i18n("Justify (HINT: for Align)", "Justify");
1031 d->propValCaption["AlignVCenter"] = i18n("Center (HINT: for Align)", "Center");
1032 d->propValCaption["AlignTop"] = i18n("Top (HINT: for Align)", "Top");
1033 d->propValCaption["AlignBottom"] = i18n("Bottom (HINT: for Align)", "Bottom");
1034
1035 d->propValCaption["NoFrame"] = i18n("No Frame (HINT: for Frame Shape)", "No Frame");
1036 d->propValCaption["Box"] = i18n("Box (HINT: for Frame Shape)", "Box");
1037 d->propValCaption["Panel"] = i18n("Panel (HINT: for Frame Shape)", "Panel");
1038 d->propValCaption["WinPanel"] = i18n("Windows Panel (HINT: for Frame Shape)", "Windows Panel");
1039 d->propValCaption["HLine"] = i18n("Horiz. Line (HINT: for Frame Shape)", "Horiz. Line");
1040 d->propValCaption["VLine"] = i18n("Vertical Line (HINT: for Frame Shape)", "Vertical Line");
1041 d->propValCaption["StyledPanel"] = i18n("Styled (HINT: for Frame Shape)", "Styled");
1042 d->propValCaption["PopupPanel"] = i18n("Popup (HINT: for Frame Shape)", "Popup");
1043 d->propValCaption["MenuBarPanel"] = i18n("Menu Bar (HINT: for Frame Shape)", "Menu Bar");
1044 d->propValCaption["ToolBarPanel"] = i18n("Toolbar (HINT: for Frame Shape)", "Toolbar");
1045 d->propValCaption["LineEditPanel"] = i18n("Text Box (HINT: for Frame Shape)", "Text Box");
1046 d->propValCaption["TabWidgetPanel"] = i18n("Tab Widget (HINT: for Frame Shape)", "Tab Widget");
1047 d->propValCaption["GroupBoxPanel"] = i18n("Group Box (HINT: for Frame Shape)", "Group Box");
1048
1049 d->propValCaption["Plain"] = i18n("Plain (HINT: for Frame Shadow)", "Plain");
1050 d->propValCaption["Raised"] = i18n("Raised (HINT: for Frame Shadow)", "Raised");
1051 d->propValCaption["Sunken"] = i18n("Sunken (HINT: for Frame Shadow)", "Sunken");
1052 d->propValCaption["MShadow"] = i18n("for Frame Shadow", "Internal");
1053
1054 d->propValCaption["NoFocus"] = i18n("No Focus (HINT: for Focus)", "No Focus");
1055 d->propValCaption["TabFocus"] = i18n("Tab (HINT: for Focus)", "Tab");
1056 d->propValCaption["ClickFocus"] = i18n("Click (HINT: for Focus)", "Click");
1057 d->propValCaption["StrongFocus"] = i18n("Tab/Click (HINT: for Focus)", "Tab/Click");
1058 d->propValCaption["WheelFocus"] = i18n("Tab/Click/MouseWheel (HINT: for Focus)", "Tab/Click/MouseWheel");
1059
1060 d->propValCaption["Auto"] = i18n("Auto");
1061 d->propValCaption["AlwaysOff"] = i18n("Always Off");
1062 d->propValCaption["AlwaysOn"] = i18n("Always On");
1063
1064 //orientation
1065 d->propValCaption["Horizontal"] = i18n("Horizontal");
1066 d->propValCaption["Vertical"] = i18n("Vertical");
1067}
1068
1069TQString
1070WidgetPropertySet::propertyCaption(const TQCString &name)
1071{
1072 return d->propCaption[name];
1073}
1074
1075TQString
1076WidgetPropertySet::valueCaption(const TQCString &name)
1077{
1078 return d->propValCaption[name];
1079}
1080
1081KoProperty::Property::ListData*
1082WidgetPropertySet::createValueList(WidgetInfo *winfo, const TQStringList &list)
1083{
1084// TQStringVariantMap map;
1085 TQStringList names;
1086 TQStringList::ConstIterator endIt = list.end();
1087 for(TQStringList::ConstIterator it = list.begin(); it != endIt; ++it) {
1088 TQString n( d->propValCaption[ (*it).latin1() ] );
1089 if (n.isEmpty()) { //try within factory and (maybe) parent factory
1090 if (winfo)
1091 n = KFormDesigner::FormManager::self()->activeForm()->library()->propertyDescForValue( winfo, (*it).latin1() );
1092 if (n.isEmpty())
1093 names.append( *it ); //untranslated
1094// map.insert(*it, (*it).latin1()); //untranslated
1095 else
1096 names.append( n );
1097// map.insert(*it, n);
1098 }
1099 else
1100 names.append( n );
1101// map.insert(*it, n);
1102 }
1103 return new KoProperty::Property::ListData(list, names);
1104}
1105
1106void
1107WidgetPropertySet::addPropertyCaption(const TQCString &property, const TQString &caption)
1108{
1109 if(!d->propCaption.contains(property))
1110 d->propCaption[property] = caption;
1111}
1112
1113void
1114WidgetPropertySet::addValueCaption(const TQCString &value, const TQString &caption)
1115{
1116 if(!d->propValCaption.contains(value))
1117 d->propValCaption[value] = caption;
1118}
1119
1120#include "widgetpropertyset.moc"
void addCommand(KCommand *command, bool allowExecute)
void setLayoutMargin(int margin)
Sets the margin of this Container.
Definition container.h:127
void setLayout(LayoutType type)
Layout functions.
TQWidget * widget() const
Definition container.h:94
void setLayoutSpacing(int spacing)
Sets the spacing of this Container.
Definition container.h:124
LayoutType layoutType() const
Definition container.h:110
static TQString layoutTypeToString(int type)
TQLayout * layout() const
Definition container.h:107
static LayoutType stringToLayoutType(const TQString &name)
Form * form() const
Definition container.h:91
static FormManager * self()
Access to FormManager singleton.
bool isTopLevel(TQWidget *w)
virtual void showPropertySet(WidgetPropertySet *set, bool forceReload=false, const TQCString &propertyToSelect=TQCString())
void addCommand(KCommand *command, bool execute)
Definition form.cpp:401
TQWidget * selectedWidget() const
Definition form.h:197
WidgetLibrary * library() const
Definition form.h:147
ObjectTree * objectTree() const
Definition form.h:167
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
const TQStringVariantMap * modifiedProperties() const
Definition objecttree.h:73
void addModifiedProperty(const TQCString &property, const TQVariant &oldValue)
ObjectTreeItem * lookup(const TQString &name)
This class holds properties of widget classes provided by a factory.
int customTypeForProperty(const char *propertyName) const
TQString pixmap() const
TQString propertyDescForName(WidgetInfo *winfo, const TQCString &propertyName)
TQString propertyDescForValue(WidgetInfo *winfo, const TQCString &name)
void setPropertyOptions(WidgetPropertySet &list, const WidgetInfo &winfo, TQWidget *w)
bool propertySetShouldBeReloadedAfterPropertyChange(const TQCString &classname, TQWidget *w, const TQCString &property)
const TQMetaProperty * findMetaSubproperty(const char *name) const
KEXIUTILS_EXPORT bool isIdentifier(const TQString &s)