summaryrefslogtreecommitdiffstats
path: root/kexi/formeditor/widgetpropertyset.cpp
diff options
context:
space:
mode:
authortpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-01-20 01:29:50 +0000
committertpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-01-20 01:29:50 +0000
commit8362bf63dea22bbf6736609b0f49c152f975eb63 (patch)
tree0eea3928e39e50fae91d4e68b21b1e6cbae25604 /kexi/formeditor/widgetpropertyset.cpp
downloadkoffice-8362bf63dea22bbf6736609b0f49c152f975eb63.tar.gz
koffice-8362bf63dea22bbf6736609b0f49c152f975eb63.zip
Added old abandoned KDE3 version of koffice
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/koffice@1077364 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'kexi/formeditor/widgetpropertyset.cpp')
-rw-r--r--kexi/formeditor/widgetpropertyset.cpp1120
1 files changed, 1120 insertions, 0 deletions
diff --git a/kexi/formeditor/widgetpropertyset.cpp b/kexi/formeditor/widgetpropertyset.cpp
new file mode 100644
index 00000000..497fb5e6
--- /dev/null
+++ b/kexi/formeditor/widgetpropertyset.cpp
@@ -0,0 +1,1120 @@
+/* This file is part of the KDE project
+ Copyright (C) 2004 Cedric Pasteur <cedric.pasteur@free.fr>
+ Copyright (C) 2004-2006 Jaroslaw Staniek <js@iidea.pl>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+#include "widgetpropertyset.h"
+
+#include <qstringlist.h>
+#include <qstrlist.h>
+#include <qmetaobject.h>
+#include <qvariant.h>
+#include <qevent.h>
+#include <qlayout.h>
+#include <qapplication.h>
+#include <qeventloop.h>
+
+#include <klocale.h>
+#include <kdebug.h>
+#include <kmessagebox.h>
+
+#include "objecttree.h"
+#include "form.h"
+#include "container.h"
+#include "formmanager.h"
+#include "widgetlibrary.h"
+#include "commands.h"
+#include "widgetwithsubpropertiesinterface.h"
+
+#include <kexiutils/utils.h>
+#include <kexiutils/identifier.h>
+
+using namespace KFormDesigner;
+
+namespace KFormDesigner {
+
+//! @internal
+typedef QValueList< QGuardedPtr<QWidget> > QGuardedWidgetList;
+
+//! @internal
+class WidgetPropertySetPrivate
+{
+ public:
+ WidgetPropertySetPrivate()
+ : lastCommand(0), lastGeoCommand(0),
+ isUndoing(false), slotPropertyChangedEnabled(true),
+ slotPropertyChanged_addCommandEnabled(true),
+ origActiveColors(0)
+ {}
+ ~WidgetPropertySetPrivate()
+ {
+ delete origActiveColors;
+ }
+
+ KoProperty::Set set;
+ // list of properties (not) to show in editor
+ QStringList properties;
+ // list of widgets
+ QGuardedWidgetList widgets;
+// FormManager *manager;
+
+ // used to update command's value when undoing
+ PropertyCommand *lastCommand;
+ GeometryPropertyCommand *lastGeoCommand;
+ bool isUndoing : 1;
+ bool slotPropertyChangedEnabled : 1;
+ bool slotPropertyChanged_addCommandEnabled : 1;
+
+ // helper to change color palette when switching 'enabled' property
+ QColorGroup* origActiveColors;
+
+ // i18n stuff
+ QMap<QCString, QString> propCaption;
+ QMap<QCString, QString> propValCaption;
+};
+}
+
+WidgetPropertySet::WidgetPropertySet(QObject *parent)
+ : QObject(parent, "kfd_widgetPropertySet")
+{
+ d = new WidgetPropertySetPrivate();
+// d->manager = manager;
+
+ connect(&d->set, SIGNAL(propertyChanged(KoProperty::Set&, KoProperty::Property&)),
+ this, SLOT(slotPropertyChanged(KoProperty::Set&, KoProperty::Property&)));
+ connect(&d->set, SIGNAL(propertyReset(KoProperty::Set&, KoProperty::Property&)),
+ this, SLOT(slotPropertyReset(KoProperty::Set&, KoProperty::Property&)));
+
+ initPropertiesDescription();
+}
+
+WidgetPropertySet::~WidgetPropertySet()
+{
+ delete d;
+}
+
+/*FormManager*
+WidgetPropertySet::manager()
+{
+ return d->manager;
+}*/
+
+KoProperty::Property&
+WidgetPropertySet::operator[](const QCString &name)
+{
+ return d->set[name];
+}
+
+KoProperty::Property&
+WidgetPropertySet::property(const QCString &name)
+{
+ return d->set[name];
+}
+
+bool
+WidgetPropertySet::contains(const QCString &property)
+{
+ return d->set.contains(property);
+}
+
+KoProperty::Set*
+WidgetPropertySet::set()
+{
+ return &(d->set);
+}
+
+void
+WidgetPropertySet::clearSet(bool dontSignalShowPropertySet)
+{
+ saveModifiedProperties();
+
+ if (!dontSignalShowPropertySet)
+ KFormDesigner::FormManager::self()->showPropertySet(0);
+ d->widgets.clear();
+ d->lastCommand = 0;
+ d->lastGeoCommand = 0;
+ d->properties.clear();
+ d->set.clear();
+
+ if(!d->widgets.isEmpty()) {
+ d->widgets.first()->removeEventFilter(this);
+ disconnect(d->widgets.first(), 0, this, 0);
+ }
+}
+
+void
+WidgetPropertySet::saveModifiedProperties()
+{
+ QWidget * w = d->widgets.first();
+ if(!w || d->widgets.count() > 1 || !KFormDesigner::FormManager::self()->activeForm() || !KFormDesigner::FormManager::self()->activeForm()->objectTree())
+ return;
+ ObjectTreeItem *tree = KFormDesigner::FormManager::self()->activeForm()->objectTree()->lookup(w->name());
+ if(!tree)
+ return;
+
+ for(KoProperty::Set::Iterator it(d->set); it.current(); ++it) {
+ if(it.current()->isModified())
+ tree->addModifiedProperty(it.current()->name(), it.current()->oldValue());
+ }
+}
+
+void
+WidgetPropertySet::setUndoing(bool isUndoing)
+{
+ d->isUndoing = isUndoing;
+}
+
+bool
+WidgetPropertySet::isUndoing()
+{
+ return d->isUndoing;
+}
+
+/////////////// Functions related to adding widgets /////////////////////////////////////
+
+void
+WidgetPropertySet::setSelectedWidget(QWidget *w, bool add, bool forceReload, bool moreWillBeSelected)
+{
+ if(!w) {
+ clearSet();
+ return;
+ }
+
+ // don't add a widget twice
+ if(!forceReload && d->widgets.contains(QGuardedPtr<QWidget>(w))) {
+ kdWarning() << "WidgetPropertySet::setSelectedWidget() Widget is already selected" << endl;
+ return;
+ }
+ // if our list is empty,don't use add parameter value
+ if(d->widgets.count() == 0)
+ add = false;
+
+ QCString prevProperty;
+ if(add)
+ addWidget(w);
+ else {
+ if (forceReload) {
+ KFormDesigner::FormManager::self()->showPropertySet(0, true/*force*/);
+ prevProperty = d->set.prevSelection();
+ }
+ clearSet(true); //clear but do not reload to avoid blinking
+ d->widgets.append(QGuardedPtr<QWidget>(w));
+ createPropertiesForWidget(w);
+
+ w->installEventFilter(this);
+ connect(w, SIGNAL(destroyed()), this, SLOT(slotWidgetDestroyed()));
+ }
+
+ if (!moreWillBeSelected)
+ KFormDesigner::FormManager::self()->showPropertySet(this, true/*force*/, prevProperty);
+}
+
+void
+WidgetPropertySet::addWidget(QWidget *w)
+{
+ d->widgets.append(QGuardedPtr<QWidget>(w));
+
+ // Reset some stuff
+ d->lastCommand = 0;
+ d->lastGeoCommand = 0;
+ d->properties.clear();
+
+ QCString classname;
+ if(d->widgets.first()->className() == w->className())
+ classname = d->widgets.first()->className();
+
+ // show only properties shared by widget (properties chosen by factory)
+ bool isTopLevel = KFormDesigner::FormManager::self()->isTopLevel(w);
+
+ //WidgetWithSubpropertiesInterface* subpropIface = dynamic_cast<WidgetWithSubpropertiesInterface*>(w);
+// QWidget *subwidget = isSubproperty ? subpropIface->subwidget() : w;
+
+ for(KoProperty::Set::Iterator it(d->set); it.current(); ++it) {
+ kdDebug() << it.currentKey() << endl;
+ if(!isPropertyVisible(it.currentKey(), isTopLevel, classname))
+ d->set[it.currentKey()].setVisible(false);
+ }
+
+ if (d->widgets.count()>=2) {
+ //second widget, update metainfo
+ d->set["this:className"].setValue("special:multiple");
+ d->set["this:classString"].setValue(
+ i18n("Multiple Widgets") + QString(" (%1)").arg(d->widgets.count()) );
+ d->set["this:iconName"].setValue("multiple_obj");
+ //name doesn't make sense for now
+ d->set["name"].setValue("");
+ }
+}
+
+void
+WidgetPropertySet::createPropertiesForWidget(QWidget *w)
+{
+ Form *form;
+ if (!KFormDesigner::FormManager::self()
+ || !(form = KFormDesigner::FormManager::self()->activeForm())
+ || !KFormDesigner::FormManager::self()->activeForm()->objectTree())
+ {
+ kdWarning() << "WidgetPropertySet::createPropertiesForWidget() no manager or active form!!!" << endl;
+ return;
+ }
+ ObjectTreeItem *tree = form->objectTree()->lookup(w->name());
+ if(!tree)
+ return;
+
+ const QVariantMap* modifiedProperties = tree->modifiedProperties();
+ QVariantMapConstIterator modifiedPropertiesIt;
+ bool isTopLevel = KFormDesigner::FormManager::self()->isTopLevel(w);
+// int count = 0;
+ KoProperty::Property *newProp = 0;
+ WidgetInfo *winfo = form->library()->widgetInfoForClassName(w->className());
+ if (!winfo) {
+ kdWarning() << "WidgetPropertySet::createPropertiesForWidget() no widget info for class "
+ << w->className() << endl;
+ return;
+ }
+
+ QStrList pList = w->metaObject()->propertyNames(true);
+ QStrListIterator it(pList);
+
+ // add subproperties if available
+ WidgetWithSubpropertiesInterface* subpropIface = dynamic_cast<WidgetWithSubpropertiesInterface*>(w);
+ QStrList tmpList; //used to allocate copy of names
+ if (subpropIface) {
+ QValueList<QCString> subproperies(
+ subpropIface->subproperies() );
+ foreach(QValueListConstIterator<QCString>, it, subproperies ) {
+ tmpList.append( *it );
+ pList.append( tmpList.last() );
+ kdDebug() << "Added subproperty: " << *it << endl;
+ }
+ }
+
+ // iterate over the property list, and create Property objects
+ for(; it.current() != 0; ++it) {
+ //kdDebug() << ">> " << it.current() << endl;
+ const QMetaProperty *subMeta = // special case - subproperty
+ subpropIface ? subpropIface->findMetaSubproperty(it.current()) : 0;
+ const QMetaProperty *meta = subMeta ? subMeta
+ : w->metaObject()->property( w->metaObject()->findProperty(*it, true), true);
+ if (!meta)
+ continue;
+ const char* propertyName = meta->name();
+ QWidget *subwidget = subMeta/*subpropIface*/ ? subpropIface->subwidget() : w;
+ WidgetInfo *subwinfo = form->library()->widgetInfoForClassName(subwidget->className());
+// kdDebug() << "$$$ " << subwidget->className() << endl;
+
+ if(subwinfo && meta->designable(subwidget) && !d->set.contains(propertyName)) {
+ //! \todo add another list for property description
+ QString desc( d->propCaption[meta->name()] );
+ //! \todo change i18n
+ if (desc.isEmpty()) //try to get property description from factory
+ desc = form->library()->propertyDescForName(subwinfo, propertyName);
+
+ modifiedPropertiesIt = modifiedProperties->find(propertyName);
+ const bool oldValueExists = modifiedPropertiesIt!=modifiedProperties->constEnd();
+
+ if(meta->isEnumType()) {
+ if(qstrcmp(propertyName, "alignment") == 0) {
+ createAlignProperty(meta, w, subwidget);
+ continue;
+ }
+
+ QStringList keys = QStringList::fromStrList( meta->enumKeys() );
+ newProp = new KoProperty::Property(propertyName, createValueList(subwinfo, keys),
+ /* assign current or older value */
+ meta->valueToKey(
+ oldValueExists ? modifiedPropertiesIt.data().toInt() : subwidget->property(propertyName).toInt() ),
+ desc, desc );
+ //now set current value, so the old one is stored as old
+ if (oldValueExists) {
+ newProp->setValue( meta->valueToKey( subwidget->property(propertyName).toInt() ) );
+ }
+ }
+ else {
+ newProp = new KoProperty::Property(propertyName,
+ /* assign current or older value */
+ oldValueExists ? modifiedPropertiesIt.data() : subwidget->property(propertyName),
+ desc, desc, subwinfo->customTypeForProperty(propertyName));
+ //now set current value, so the old one is stored as old
+ if (oldValueExists) {
+ newProp->setValue( subwidget->property(propertyName) );
+ }
+ }
+
+ d->set.addProperty(newProp);
+ if(!isPropertyVisible(propertyName, isTopLevel))
+ newProp->setVisible(false);
+ //! TMP
+ if(newProp->type() == 0) // invalid type == null pixmap ?
+ newProp->setType(KoProperty::Pixmap);
+ }
+
+// if(0==qstrcmp(propertyName, "name"))
+// (*this)["name"].setAutoSync(0); // name should be updated only when pressing Enter
+
+ // \todo js what does this mean? why do you use WidgetInfo and not WidgetLibrary
+ /*if (winfo) {
+ tristate autoSync = winfo->autoSyncForProperty( propertyName );
+ if (! ~autoSync)
+ d->set[propertyName].setAutoSync( autoSync );
+ }*/
+
+ // update the Property.oldValue() and isModified() using the value stored in the ObjectTreeItem
+ updatePropertyValue(tree, propertyName, meta);
+ }
+
+ (*this)["name"].setAutoSync(false); // name should be updated only when pressing Enter
+ (*this)["enabled"].setValue( QVariant(tree->isEnabled(), 3));
+
+ if (winfo) {
+ form->library()->setPropertyOptions(*this, *winfo, w);
+ d->set.addProperty( newProp = new KoProperty::Property("this:classString", winfo->name()) );
+ newProp->setVisible(false);
+ d->set.addProperty( newProp = new KoProperty::Property("this:iconName", winfo->pixmap()) );
+ newProp->setVisible(false);
+ }
+ d->set.addProperty( newProp = new KoProperty::Property("this:className", w->className()) );
+ newProp->setVisible(false);
+
+ /*! let's forget it for now, until we have new complete events editor
+ if (m_manager->lib()->advancedPropertiesVisible()) {
+ // add the signals property
+ QStrList strlist = w->metaObject()->signalNames(true);
+ QStrListIterator strIt(strlist);
+ QStringList list;
+ for(; strIt.current() != 0; ++strIt)
+ list.append(*strIt);
+ Property *prop = new Property("signals", i18n("Events")"",
+ new KexiProperty::ListData(list, descList(winfo, list)),
+ ));
+ }*/
+
+ if(KFormDesigner::FormManager::self()->activeForm() && tree->container()) // we are a container -> layout property
+ createLayoutProperty(tree);
+}
+
+void
+WidgetPropertySet::updatePropertyValue(ObjectTreeItem *tree, const char *property, const QMetaProperty *meta)
+{
+ const char *propertyName = meta ? meta->name() : property;
+ if (!d->set.contains(propertyName))
+ return;
+ KoProperty::Property p( d->set[propertyName] );
+
+//! \todo what about set properties, and lists properties
+ QMap<QString, QVariant>::ConstIterator it( tree->modifiedProperties()->find(propertyName) );
+ if (it != tree->modifiedProperties()->constEnd()) {
+ blockSignals(true);
+ if(meta && meta->isEnumType()) {
+ p.setValue( meta->valueToKey( it.data().toInt() ), false );
+ }
+ else {
+ p.setValue(it.data(), false );
+ }
+ p.setValue(p.value(), true);
+ blockSignals(false);
+ }
+}
+
+bool
+WidgetPropertySet::isPropertyVisible(const QCString &property, bool isTopLevel, const QCString &classname)
+{
+ const bool multiple = d->widgets.count() >= 2;
+ if(multiple && classname.isEmpty())
+ return false;
+/* moved to WidgetLibrary::isPropertyVisible()
+ if(d->widgets.count() < 2)
+ {
+ if(d->properties.isEmpty() && !isTopLevel)
+ d->properties << "caption" << "icon" << "sizeIncrement" << "iconText";
+ // don't show these properties for a non-toplevel widget
+
+ if(! (d->properties.grep(property)).isEmpty() )
+ return false;
+ }
+ else
+ {
+ if(classname.isEmpty())
+ return false;
+
+ if(d->properties.isEmpty()) {
+ d->properties << "font" << "paletteBackgroundColor" << "enabled" << "paletteForegroundColor"
+ << "cursor" << "paletteBackgroundPixmap";
+ } // properties always shown in multiple mode
+ if(! (d->properties.grep(property)).isEmpty() )
+ return true;
+ }
+*/
+
+// return KFormDesigner::FormManager::self()->lib()->isPropertyVisible(d->widgets.first()->className(), d->widgets.first(),
+ QWidget *w = d->widgets.first();
+ WidgetWithSubpropertiesInterface* subpropIface = dynamic_cast<WidgetWithSubpropertiesInterface*>(w);
+ QWidget *subwidget;
+ if (subpropIface && subpropIface->findMetaSubproperty(property)) // special case - subproperty
+ subwidget = subpropIface->subwidget();
+ else
+ subwidget = w;
+
+ return KFormDesigner::FormManager::self()->activeForm()->library()->isPropertyVisible(
+ subwidget->className(), subwidget, property, multiple, isTopLevel);
+}
+
+//////////////// Slots called when properties are modified ///////////////
+
+void
+WidgetPropertySet::slotPropertyChanged(KoProperty::Set& set, KoProperty::Property& p)
+{
+ Q_UNUSED( set );
+
+ if(!d->slotPropertyChangedEnabled || !KFormDesigner::FormManager::self() || !KFormDesigner::FormManager::self()->activeForm()
+ || ! KFormDesigner::FormManager::self()->activeForm()->objectTree())
+ return;
+
+ QCString property = p.name();
+ if (0==property.find("this:"))
+ return; //starts with magical prefix: it's a "meta" prop.
+
+ QVariant value = p.value();
+
+ // check if the name is valid (ie is correct identifier) and there is no name conflict
+ if(property == "name") {
+ if(d->widgets.count()!=1)
+ return;
+ if(!isNameValid(value.toString()))
+ return;
+ }
+ // a widget with a background pixmap should have its own origin
+ else if(property == "paletteBackgroundPixmap") {
+ d->set["backgroundOrigin"] = "WidgetOrigin";
+ //else if(property == "signals")
+ // return;
+ // special types of properties handled separately
+ } else if((property == "hAlign") || (property == "vAlign") || (property == "wordbreak")) {
+ saveAlignProperty(property);
+ return;
+ }
+ else if((property == "layout") || (property == "layoutMargin") || (property == "layoutSpacing")) {
+ saveLayoutProperty(property, value);
+ return;
+ }
+ // we cannot really disable the widget, we just change its color palette
+ else if(property == "enabled") {
+ saveEnabledProperty(value.toBool());
+ return;
+ }
+
+ // make sure we are not already undoing -> avoid recursion
+ if(d->isUndoing && !KFormDesigner::FormManager::self()->isRedoing())
+ return;
+
+ const bool alterLastCommand = d->lastCommand && d->lastCommand->property() == property;
+
+ if(d->widgets.count() == 1) // one widget selected
+ {
+ // If the last command is the same, we just change its value
+ if(alterLastCommand && !KFormDesigner::FormManager::self()->isRedoing())
+ d->lastCommand->setValue(value);
+ else {
+// if(m_widgets.first() && ((m_widgets.first() != m_manager->activeForm()->widget()) || (property != "geometry"))) {
+ if (d->slotPropertyChanged_addCommandEnabled && !KFormDesigner::FormManager::self()->isRedoing()) {
+ d->lastCommand = new PropertyCommand(this, d->widgets.first()->name(),
+ d->widgets.first()->property(property), value, property);
+ KFormDesigner::FormManager::self()->activeForm()->addCommand(d->lastCommand, false);
+ }
+
+ // If the property is changed, we add it in ObjectTreeItem modifProp
+ ObjectTreeItem *tree = KFormDesigner::FormManager::self()->activeForm()->objectTree()->lookup(d->widgets.first()->name());
+ if (tree && p.isModified())
+ tree->addModifiedProperty(property, d->widgets.first()->property(property));
+ }
+
+ if(property == "name")
+ emit widgetNameChanged(d->widgets.first()->name(), p.value().toCString());
+ d->widgets.first()->setProperty(property, value);
+ emitWidgetPropertyChanged(d->widgets.first(), property, value);
+ }
+ else
+ {
+ if(alterLastCommand && !KFormDesigner::FormManager::self()->isRedoing())
+ d->lastCommand->setValue(value);
+ else {
+ if (d->slotPropertyChanged_addCommandEnabled && !KFormDesigner::FormManager::self()->isRedoing()) {
+ // We store old values for each widget
+ QMap<QCString, QVariant> list;
+ // for(QWidget *w = d->widgets.first(); w; w = d->widgets.next())
+ foreach(QGuardedWidgetList::ConstIterator, it, d->widgets)
+ list.insert((*it)->name(), (*it)->property(property));
+
+ d->lastCommand = new PropertyCommand(this, list, value, property);
+ KFormDesigner::FormManager::self()->activeForm()->addCommand(d->lastCommand, false);
+ }
+ }
+
+// for(QWidget *w = d->widgets.first(); w; w = d->widgets.next())
+ foreach(QGuardedWidgetList::ConstIterator, it, d->widgets) {
+ if (!alterLastCommand) {
+ ObjectTreeItem *tree = KFormDesigner::FormManager::self()->activeForm()->objectTree()
+ ->lookup((*it)->name());
+ if(tree && p.isModified())
+ tree->addModifiedProperty(property, (*it)->property(property));
+ }
+ (*it)->setProperty(property, value);
+ emitWidgetPropertyChanged((*it), property, value);
+ }
+ }
+}
+
+void WidgetPropertySet::emitWidgetPropertyChanged(QWidget *w, const QCString& property, const QVariant& value)
+{
+ emit widgetPropertyChanged(w, property, value);
+
+ Form *form = KFormDesigner::FormManager::self()->activeForm();
+ if (form && form->library()->propertySetShouldBeReloadedAfterPropertyChange( w->className(), w, property)) {
+ //setSelectedWidget(0, false);
+ qApp->eventLoop()->processEvents(QEventLoop::AllEvents); //be sure events related to editors are consumed
+ setSelectedWidget(w, /*!add*/false, /*forceReload*/true);
+ qApp->eventLoop()->processEvents(QEventLoop::AllEvents); //be sure events related to editors are consumed
+ //KFormDesigner::FormManager::self()->showPropertySet(this, true/*forceReload*/);
+ }
+}
+
+void
+WidgetPropertySet::createPropertyCommandsInDesignMode(QWidget* widget,
+ const QMap<QCString, QVariant> &propValues, CommandGroup *group, bool addToActiveForm,
+ bool execFlagForSubCommands)
+{
+ if (!widget || propValues.isEmpty())
+ return;
+
+ //is this widget selected? (if so, use property system)
+ const bool widgetIsSelected = KFormDesigner::FormManager::self()->activeForm()->selectedWidget() == widget;
+
+ d->slotPropertyChanged_addCommandEnabled = false;
+ QMap<QCString, QVariant>::ConstIterator endIt = propValues.constEnd();
+// CommandGroup *group = new CommandGroup(commandName);
+ for(QMap<QCString, QVariant>::ConstIterator it = propValues.constBegin(); it != endIt; ++it)
+ {
+ if (!d->set.contains(it.key())) {
+ kdWarning() << "WidgetPropertySet::createPropertyCommandsInDesignMode(): \"" <<it.key()<<"\" property not found"<<endl;
+ continue;
+ }
+ PropertyCommand *subCommand = new PropertyCommand(this, widget->name(),
+ widget->property(it.key()), it.data(), it.key());
+ group->addCommand( subCommand, execFlagForSubCommands);
+ if (widgetIsSelected) {
+ d->set[it.key()].setValue(it.data());
+ }
+ else {
+ WidgetWithSubpropertiesInterface* subpropIface = dynamic_cast<WidgetWithSubpropertiesInterface*>(widget);
+ QWidget *subwidget = (subpropIface && subpropIface->subwidget()) ? subpropIface->subwidget() : widget;
+ if (-1 != subwidget->metaObject()->findProperty(it.key(), true) && subwidget->property(it.key())!=it.data()) {
+ ObjectTreeItem *tree = KFormDesigner::FormManager::self()->activeForm()->objectTree()->lookup(widget->name());
+ if (tree)
+ tree->addModifiedProperty(it.key(), subwidget->property(it.key()));
+ subwidget->setProperty(it.key(), it.data());
+ emit widgetPropertyChanged(widget, it.key(), it.data());
+ }
+ }
+ }
+ d->lastCommand = 0;
+ if (addToActiveForm)
+ KFormDesigner::FormManager::self()->activeForm()->addCommand(group, false/*no exec*/);
+ d->slotPropertyChanged_addCommandEnabled = true;
+// }
+}
+
+//! \todo make it support undo
+void
+WidgetPropertySet::saveEnabledProperty(bool value)
+{
+// for(QWidget *w = d->widgets.first(); w; w = d->widgets.next()) {
+ foreach(QGuardedWidgetList::ConstIterator, it, d->widgets) {
+ ObjectTreeItem *tree = KFormDesigner::FormManager::self()->activeForm()->objectTree()
+ ->lookup((*it)->name());
+ if(tree->isEnabled() == value)
+ continue;
+
+ QPalette p( (*it)->palette() );
+ if (!d->origActiveColors)
+ d->origActiveColors = new QColorGroup( p.active() );
+ if (value) {
+ if (d->origActiveColors)
+ p.setActive( *d->origActiveColors ); //revert
+ }
+ else {
+ QColorGroup cg = p.disabled();
+ //also make base color a bit disabled-like
+ cg.setColor(QColorGroup::Base, cg.color(QColorGroup::Background));
+ p.setActive(cg);
+ }
+ (*it)->setPalette(p);
+
+ tree->setEnabled(value);
+ emit widgetPropertyChanged((*it), "enabled", QVariant(value, 3));
+ }
+}
+
+bool
+WidgetPropertySet::isNameValid(const QString &name)
+{
+ //! \todo add to undo buffer
+ QWidget *w = d->widgets.first();
+ //also update widget's name in QObject member
+ if (!KexiUtils::isIdentifier(name)) {
+ KMessageBox::sorry(KFormDesigner::FormManager::self()->activeForm()->widget(),
+ i18n("Could not rename widget \"%1\" to \"%2\" because "
+ "\"%3\" is not a valid name (identifier) for a widget.\n")
+ .arg(w->name()).arg(name).arg(name));
+ d->slotPropertyChangedEnabled = false;
+ d->set["name"].resetValue();
+ d->slotPropertyChangedEnabled = true;
+ return false;
+ }
+
+ if (KFormDesigner::FormManager::self()->activeForm()->objectTree()->lookup(name)) {
+ KMessageBox::sorry( KFormDesigner::FormManager::self()->activeForm()->widget(),
+ i18n("Could not rename widget \"%1\" to \"%2\" "
+ "because a widget with the name \"%3\" already exists.\n")
+ .arg(w->name()).arg(name).arg(name));
+ d->slotPropertyChangedEnabled = false;
+ d->set["name"].resetValue();
+ d->slotPropertyChangedEnabled = true;
+ return false;
+ }
+
+ return true; //ie name is correct
+}
+
+void
+WidgetPropertySet::slotPropertyReset(KoProperty::Set& set, KoProperty::Property& property)
+{
+ Q_UNUSED( set );
+
+ if(d->widgets.count() < 2)
+ return;
+
+ // We use the old value in modifProp for each widget
+// for(QWidget *w = d->widgets.first(); w; w = d->widgets.next()) {
+ foreach(QGuardedWidgetList::ConstIterator, it, d->widgets) {
+ ObjectTreeItem *tree = KFormDesigner::FormManager::self()->activeForm()->objectTree()->lookup((*it)->name());
+ if(tree->modifiedProperties()->contains(property.name()))
+ (*it)->setProperty(property.name(), tree->modifiedProperties()->find(property.name()).data());
+ }
+}
+
+void
+WidgetPropertySet::slotWidgetDestroyed()
+{
+// if(d->widgets.contains(QGuardedPtr<const QWidget>( dynamic_cast<const QWidget*>(sender()) ))) {
+ //only clear this set if it contains the destroyed widget
+ foreach(QGuardedWidgetList::ConstIterator, it, d->widgets) {
+ if (dynamic_cast<const QWidget*>(sender()) == *it) {
+ clearSet();
+ break;
+ }
+ }
+}
+
+bool
+WidgetPropertySet::eventFilter(QObject *o, QEvent *ev)
+{
+ if(d->widgets.count() > 0 && o == d->widgets.first() && d->widgets.count() < 2)
+ {
+ if((ev->type() == QEvent::Resize) || (ev->type() == QEvent::Move)) {
+ if(!d->set.contains("geometry"))
+ return false;
+ if(d->set["geometry"].value() == o->property("geometry")) // to avoid infinite recursion
+ return false;
+
+ d->set["geometry"] = static_cast<QWidget*>(o)->geometry();
+ }
+ }
+ else if(d->widgets.count() > 1 && ev->type() == QEvent::Move) // the widget is being moved, we update the property
+ {
+ if(d->isUndoing)
+ return false;
+
+ if(d->lastGeoCommand)
+ d->lastGeoCommand->setPos(static_cast<QMoveEvent*>(ev)->pos());
+ else {
+ QStringList list;
+ foreach(QGuardedWidgetList::ConstIterator, it, d->widgets)
+ list.append((*it)->name());
+
+ d->lastGeoCommand = new GeometryPropertyCommand(this, list, static_cast<QMoveEvent*>(ev)->oldPos());
+ if (KFormDesigner::FormManager::self()->activeForm())
+ KFormDesigner::FormManager::self()->activeForm()->addCommand(d->lastGeoCommand, false);
+ }
+ }
+
+ return false;
+}
+
+// Alignment-related functions /////////////////////////////
+
+void
+WidgetPropertySet::createAlignProperty(const QMetaProperty *meta, QWidget *widget, QWidget *subwidget)
+{
+ if (!KFormDesigner::FormManager::self()->activeForm()
+|| !KFormDesigner::FormManager::self()->activeForm()->objectTree())
+ return;
+
+ QStringList list;
+ QString value;
+ const int alignment = subwidget->property("alignment").toInt();
+ const QStringList keys( QStringList::fromStrList( meta->valueToKeys(alignment) ) );
+
+ QStrList *enumKeys = new QStrList(meta->enumKeys());
+ const QStringList possibleValues( QStringList::fromStrList(*enumKeys) );
+ delete enumKeys;
+
+ ObjectTreeItem *tree = KFormDesigner::FormManager::self()->activeForm()->objectTree()->lookup(widget->name());
+ bool isTopLevel = KFormDesigner::FormManager::self()->isTopLevel(widget);
+
+ if(possibleValues.find("AlignHCenter")!=possibleValues.constEnd()) {
+ // Create the horizontal alignment property
+ if(keys.find("AlignHCenter")!=keys.constEnd() || keys.find("AlignCenter")!=keys.constEnd())
+ value = "AlignHCenter";
+ else if(keys.find("AlignRight")!=keys.constEnd())
+ value = "AlignRight";
+ else if(keys.find("AlignLeft")!=keys.constEnd())
+ value = "AlignLeft";
+ else if(keys.find("AlignJustify")!=keys.constEnd())
+ value = "AlignJustify";
+ else
+ value = "AlignAuto";
+
+ list << "AlignAuto" << "AlignLeft" << "AlignRight" << "AlignHCenter" << "AlignJustify";
+ KoProperty::Property *p = new KoProperty::Property("hAlign", createValueList(0, list), value,
+ i18n("Translators: please keep this string short (less than 20 chars)", "Hor. Alignment"),
+ i18n("Horizontal Alignment"));
+ d->set.addProperty(p);
+ if(!isPropertyVisible(p->name(), isTopLevel)) {
+ p->setVisible(false);
+ }
+ updatePropertyValue(tree, "hAlign");
+ list.clear();
+ }
+
+ if(possibleValues.find("AlignTop")!=possibleValues.constEnd())
+ {
+ // Create the ver alignment property
+ if(keys.find("AlignTop")!=keys.constEnd())
+ value = "AlignTop";
+ else if(keys.find("AlignBottom")!=keys.constEnd())
+ value = "AlignBottom";
+ else
+ value = "AlignVCenter";
+
+ list << "AlignTop" << "AlignVCenter" << "AlignBottom";
+ KoProperty::Property *p = new KoProperty::Property("vAlign", createValueList(0, list), value,
+ i18n("Translators: please keep this string short (less than 20 chars)", "Ver. Alignment"),
+ i18n("Vertical Alignment"));
+ d->set.addProperty(p);
+ if(!isPropertyVisible(p->name(), isTopLevel)) {
+ p->setVisible(false);
+ }
+ updatePropertyValue(tree, "vAlign");
+ }
+
+ if(possibleValues.find("WordBreak")!=possibleValues.constEnd()
+// && isPropertyVisible("wordbreak", false, subwidget->className())
+// && !subWidget->inherits("QLineEdit") /* QLineEdit doesn't support 'word break' is this generic enough?*/
+ ) {
+ // Create the wordbreak property
+ KoProperty::Property *p = new KoProperty::Property("wordbreak",
+ QVariant(alignment & Qt::WordBreak, 3), i18n("Word Break"), i18n("Word Break") );
+ d->set.addProperty(p);
+ updatePropertyValue(tree, "wordbreak");
+ if (!KFormDesigner::FormManager::self()->activeForm()->library()->isPropertyVisible(
+ subwidget->className(), subwidget, p->name(), false/*multiple*/, isTopLevel))
+ {
+ p->setVisible(false);
+ }
+ }
+}
+
+void
+WidgetPropertySet::saveAlignProperty(const QString &property)
+{
+ if (!KFormDesigner::FormManager::self()->activeForm())
+ return;
+
+ QStrList list;
+ if( d->set.contains("hAlign") )
+ list.append( d->set["hAlign"].value().toCString() );
+ if( d->set.contains("vAlign") )
+ list.append( d->set["vAlign"].value().toCString() );
+ if( d->set.contains("wordbreak") && d->set["wordbreak"].value().toBool() )
+ list.append("WordBreak");
+
+ WidgetWithSubpropertiesInterface* subpropIface = dynamic_cast<WidgetWithSubpropertiesInterface*>(
+ (QWidget*)d->widgets.first() );
+ QWidget *subwidget = (subpropIface && subpropIface->subwidget()) ? subpropIface->subwidget() : (QWidget*)d->widgets.first();
+ int count = subwidget->metaObject()->findProperty("alignment", true);
+ const QMetaProperty *meta = subwidget->metaObject()->property(count, true);
+ subwidget->setProperty("alignment", meta->keysToValue(list));
+
+ ObjectTreeItem *tree = KFormDesigner::FormManager::self()->activeForm()->objectTree()->lookup(
+ d->widgets.first()->name() );
+ if(tree && d->set[property.latin1()].isModified())
+ tree->addModifiedProperty(property.latin1(), d->set[property.latin1()].oldValue());
+
+ if(d->isUndoing)
+ return;
+
+ if(d->lastCommand && d->lastCommand->property() == "alignment")
+ d->lastCommand->setValue(meta->keysToValue(list));
+ else {
+ d->lastCommand = new PropertyCommand(this, d->widgets.first()->name(),
+ subwidget->property("alignment"), meta->keysToValue(list), "alignment");
+ KFormDesigner::FormManager::self()->activeForm()->addCommand(d->lastCommand, false);
+ }
+}
+
+// Layout-related functions //////////////////////////
+
+void
+WidgetPropertySet::createLayoutProperty(ObjectTreeItem *item)
+{
+ Container *container = item->container();
+ if (!container || !KFormDesigner::FormManager::self()->activeForm() ||
+ !KFormDesigner::FormManager::self()->activeForm()->objectTree() || !container->widget())
+ return;
+ // special containers have no 'layout' property, as it should not be changed
+ QCString className = container->widget()->className();
+ if((className == "HBox") || (className == "VBox") || (className == "Grid"))
+ return;
+
+ QStringList list;
+ QString value = Container::layoutTypeToString(container->layoutType());
+
+ list << "NoLayout" << "HBox" << "VBox" << "Grid" << "HFlow" << "VFlow";
+
+ KoProperty::Property *p = new KoProperty::Property("layout", createValueList(0, list), value,
+ i18n("Container's Layout"), i18n("Container's Layout"));
+ p->setVisible( container->form()->library()->advancedPropertiesVisible() );
+ d->set.addProperty(p);
+
+ updatePropertyValue(item, "layout");
+
+ p = new KoProperty::Property("layoutMargin", container->layoutMargin(), i18n("Layout Margin"), i18n("Layout Margin"));
+ d->set.addProperty(p);
+ updatePropertyValue(item, "layoutMargin");
+ if(container->layoutType() == Container::NoLayout)
+ p->setVisible(false);
+
+ p = new KoProperty::Property("layoutSpacing", container->layoutSpacing(),
+ i18n("Layout Spacing"), i18n("Layout Spacing"));
+ d->set.addProperty(p);
+ updatePropertyValue(item, "layoutSpacing");
+ if(container->layoutType() == Container::NoLayout)
+ p->setVisible(false);
+
+}
+
+void
+WidgetPropertySet::saveLayoutProperty(const QString &prop, const QVariant &value)
+{
+ Container *container=0;
+ if(!KFormDesigner::FormManager::self()->activeForm() || !KFormDesigner::FormManager::self()->activeForm()->objectTree())
+ return;
+ ObjectTreeItem *item = KFormDesigner::FormManager::self()->activeForm()->objectTree()->lookup(d->widgets.first()->name());
+ if(!item)
+ return;
+ container = item->container();
+
+ if(prop == "layout") {
+ Container::LayoutType type = Container::stringToLayoutType(value.toString());
+
+ if(d->lastCommand && d->lastCommand->property() == "layout" && !d->isUndoing)
+ d->lastCommand->setValue(value);
+ else if(!d->isUndoing) {
+ d->lastCommand = new LayoutPropertyCommand(this, d->widgets.first()->name(),
+ d->set["layout"].oldValue(), value);
+ KFormDesigner::FormManager::self()->activeForm()->addCommand(d->lastCommand, false);
+ }
+
+ container->setLayout(type);
+ bool show = (type != Container::NoLayout);
+ if(show != d->set["layoutMargin"].isVisible()) {
+ d->set["layoutMargin"].setVisible(show);
+ d->set["layoutSpacing"].setVisible(show);
+ KFormDesigner::FormManager::self()->showPropertySet(this, true/*force*/);
+ }
+ return;
+ }
+
+ if(prop == "layoutMargin" && container->layout()) {
+ container->setLayoutMargin(value.toInt());
+ container->layout()->setMargin(value.toInt());
+ }
+ else if(prop == "layoutSpacing" && container->layout()) {
+ container->setLayoutSpacing(value.toInt());
+ container->layout()->setSpacing(value.toInt());
+ }
+
+ ObjectTreeItem *tree = KFormDesigner::FormManager::self()->activeForm()->objectTree()->lookup(d->widgets.first()->name());
+ if(tree && d->set[ prop.latin1() ].isModified())
+ tree->addModifiedProperty(prop.latin1(), d->set[prop.latin1()].oldValue());
+
+ if(d->isUndoing)
+ return;
+
+ if(d->lastCommand && (QString(d->lastCommand->property()) == prop))
+ d->lastCommand->setValue(value);
+ else {
+ d->lastCommand = new PropertyCommand(this, d->widgets.first()->name(),
+ d->set[ prop.latin1() ].oldValue(), value, prop.latin1());
+ KFormDesigner::FormManager::self()->activeForm()->addCommand(d->lastCommand, false);
+ }
+}
+
+
+
+////////////////////////////////////////// i18n related functions ////////
+
+void
+WidgetPropertySet::initPropertiesDescription()
+{
+//! \todo perhaps a few of them shouldn't be translated within KFD mode,
+//! to be more Qt Designer friendly?
+ d->propCaption["name"] = i18n("Name");
+ d->propCaption["caption"] = i18n("Caption");
+ d->propCaption["text"] = i18n("Text");
+ d->propCaption["paletteBackgroundPixmap"] = i18n("Background Pixmap");
+ d->propCaption["enabled"] = i18n("Enabled");
+ d->propCaption["geometry"] = i18n("Geometry");
+ d->propCaption["sizePolicy"] = i18n("Size Policy");
+ d->propCaption["minimumSize"] = i18n("Minimum Size");
+ d->propCaption["maximumSize"] = i18n("Maximum Size");
+ d->propCaption["font"] = i18n("Font");
+ d->propCaption["cursor"] = i18n("Cursor");
+ d->propCaption["paletteForegroundColor"] = i18n("Foreground Color");
+ d->propCaption["paletteBackgroundColor"] = i18n("Background Color");
+ d->propCaption["focusPolicy"] = i18n("Focus Policy");
+ d->propCaption["margin"] = i18n("Margin");
+ d->propCaption["readOnly"] = i18n("Read Only");
+ //any QFrame
+ d->propCaption["frame"] = i18n("Frame");
+ d->propCaption["lineWidth"] = i18n("Frame Width");
+ d->propCaption["midLineWidth"] = i18n("Mid Frame Width");
+ d->propCaption["frameShape"] = i18n("Frame Shape");
+ d->propCaption["frameShadow"] = i18n("Frame Shadow");
+ //any QScrollbar
+ d->propCaption["vScrollBarMode"] = i18n("Vertical ScrollBar");
+ d->propCaption["hScrollBarMode"] = i18n("Horizontal ScrollBar");
+
+ d->propValCaption["NoBackground"] = i18n("No Background");
+ d->propValCaption["PaletteForeground"] = i18n("Palette Foreground");
+ d->propValCaption["AutoText"] = i18n("Auto (HINT: for AutoText)", "Auto");
+
+ d->propValCaption["AlignAuto"] = i18n("Auto (HINT: for Align)", "Auto");
+ d->propValCaption["AlignLeft"] = i18n("Left (HINT: for Align)", "Left");
+ d->propValCaption["AlignRight"] = i18n("Right (HINT: for Align)", "Right");
+ d->propValCaption["AlignHCenter"] = i18n("Center (HINT: for Align)", "Center");
+ d->propValCaption["AlignJustify"] = i18n("Justify (HINT: for Align)", "Justify");
+ d->propValCaption["AlignVCenter"] = i18n("Center (HINT: for Align)", "Center");
+ d->propValCaption["AlignTop"] = i18n("Top (HINT: for Align)", "Top");
+ d->propValCaption["AlignBottom"] = i18n("Bottom (HINT: for Align)", "Bottom");
+
+ d->propValCaption["NoFrame"] = i18n("No Frame (HINT: for Frame Shape)", "No Frame");
+ d->propValCaption["Box"] = i18n("Box (HINT: for Frame Shape)", "Box");
+ d->propValCaption["Panel"] = i18n("Panel (HINT: for Frame Shape)", "Panel");
+ d->propValCaption["WinPanel"] = i18n("Windows Panel (HINT: for Frame Shape)", "Windows Panel");
+ d->propValCaption["HLine"] = i18n("Horiz. Line (HINT: for Frame Shape)", "Horiz. Line");
+ d->propValCaption["VLine"] = i18n("Vertical Line (HINT: for Frame Shape)", "Vertical Line");
+ d->propValCaption["StyledPanel"] = i18n("Styled (HINT: for Frame Shape)", "Styled");
+ d->propValCaption["PopupPanel"] = i18n("Popup (HINT: for Frame Shape)", "Popup");
+ d->propValCaption["MenuBarPanel"] = i18n("Menu Bar (HINT: for Frame Shape)", "Menu Bar");
+ d->propValCaption["ToolBarPanel"] = i18n("Toolbar (HINT: for Frame Shape)", "Toolbar");
+ d->propValCaption["LineEditPanel"] = i18n("Text Box (HINT: for Frame Shape)", "Text Box");
+ d->propValCaption["TabWidgetPanel"] = i18n("Tab Widget (HINT: for Frame Shape)", "Tab Widget");
+ d->propValCaption["GroupBoxPanel"] = i18n("Group Box (HINT: for Frame Shape)", "Group Box");
+
+ d->propValCaption["Plain"] = i18n("Plain (HINT: for Frame Shadow)", "Plain");
+ d->propValCaption["Raised"] = i18n("Raised (HINT: for Frame Shadow)", "Raised");
+ d->propValCaption["Sunken"] = i18n("Sunken (HINT: for Frame Shadow)", "Sunken");
+ d->propValCaption["MShadow"] = i18n("for Frame Shadow", "Internal");
+
+ d->propValCaption["NoFocus"] = i18n("No Focus (HINT: for Focus)", "No Focus");
+ d->propValCaption["TabFocus"] = i18n("Tab (HINT: for Focus)", "Tab");
+ d->propValCaption["ClickFocus"] = i18n("Click (HINT: for Focus)", "Click");
+ d->propValCaption["StrongFocus"] = i18n("Tab/Click (HINT: for Focus)", "Tab/Click");
+ d->propValCaption["WheelFocus"] = i18n("Tab/Click/MouseWheel (HINT: for Focus)", "Tab/Click/MouseWheel");
+
+ d->propValCaption["Auto"] = i18n("Auto");
+ d->propValCaption["AlwaysOff"] = i18n("Always Off");
+ d->propValCaption["AlwaysOn"] = i18n("Always On");
+
+ //orientation
+ d->propValCaption["Horizontal"] = i18n("Horizontal");
+ d->propValCaption["Vertical"] = i18n("Vertical");
+}
+
+QString
+WidgetPropertySet::propertyCaption(const QCString &name)
+{
+ return d->propCaption[name];
+}
+
+QString
+WidgetPropertySet::valueCaption(const QCString &name)
+{
+ return d->propValCaption[name];
+}
+
+KoProperty::Property::ListData*
+WidgetPropertySet::createValueList(WidgetInfo *winfo, const QStringList &list)
+{
+// QMap <QString, QVariant> map;
+ QStringList names;
+ QStringList::ConstIterator endIt = list.end();
+ for(QStringList::ConstIterator it = list.begin(); it != endIt; ++it) {
+ QString n( d->propValCaption[ (*it).latin1() ] );
+ if (n.isEmpty()) { //try within factory and (maybe) parent factory
+ if (winfo)
+ n = KFormDesigner::FormManager::self()->activeForm()->library()->propertyDescForValue( winfo, (*it).latin1() );
+ if (n.isEmpty())
+ names.append( *it ); //untranslated
+// map.insert(*it, (*it).latin1()); //untranslated
+ else
+ names.append( n );
+// map.insert(*it, n);
+ }
+ else
+ names.append( n );
+// map.insert(*it, n);
+ }
+ return new KoProperty::Property::ListData(list, names);
+}
+
+void
+WidgetPropertySet::addPropertyCaption(const QCString &property, const QString &caption)
+{
+ if(!d->propCaption.contains(property))
+ d->propCaption[property] = caption;
+}
+
+void
+WidgetPropertySet::addValueCaption(const QCString &value, const QString &caption)
+{
+ if(!d->propValCaption.contains(value))
+ d->propValCaption[value] = caption;
+}
+
+#include "widgetpropertyset.moc"