kexi

widgetpropertyset.cpp

00001 /* This file is part of the KDE project
00002    Copyright (C) 2004 Cedric Pasteur <cedric.pasteur@free.fr>
00003    Copyright (C) 2004-2006 Jaroslaw Staniek <js@iidea.pl>
00004 
00005    This library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Library General Public
00007    License as published by the Free Software Foundation; either
00008    version 2 of the License, or (at your option) any later version.
00009 
00010    This library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Library General Public License for more details.
00014 
00015    You should have received a copy of the GNU Library General Public License
00016    along with this library; see the file COPYING.LIB.  If not, write to
00017    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018  * Boston, MA 02110-1301, USA.
00019 */
00020 #include "widgetpropertyset.h"
00021 
00022 #include <qstringlist.h>
00023 #include <qstrlist.h>
00024 #include <qmetaobject.h>
00025 #include <qvariant.h>
00026 #include <qevent.h>
00027 #include <qlayout.h>
00028 
00029 #include <klocale.h>
00030 #include <kdebug.h>
00031 #include <kmessagebox.h>
00032 
00033 #include "objecttree.h"
00034 #include "form.h"
00035 #include "container.h"
00036 #include "formmanager.h"
00037 #include "widgetlibrary.h"
00038 #include "commands.h"
00039 
00040 #include <kexiutils/utils.h>
00041 #include <kexiutils/identifier.h>
00042 
00043 using namespace KFormDesigner;
00044 
00045 namespace KFormDesigner {
00046 
00048 typedef QValueList< QGuardedPtr<QWidget> > QGuardedWidgetList;
00049 
00051 class WidgetPropertySetPrivate
00052 {
00053     public:
00054         WidgetPropertySetPrivate()
00055         : lastCommand(0), lastGeoCommand(0),
00056          isUndoing(false), slotPropertyChangedEnabled(true),
00057          slotPropertyChanged_addCommandEnabled(true),
00058          origActiveColors(0)
00059         {}
00060         ~WidgetPropertySetPrivate()
00061         {
00062             delete origActiveColors;
00063         }
00064 
00065         KoProperty::Set  set;
00066         // list of properties (not) to show in editor
00067         QStringList  properties;
00068         // list of widgets
00069         QGuardedWidgetList widgets;
00070 //      FormManager  *manager;
00071 
00072         // used to update command's value when undoing
00073         PropertyCommand  *lastCommand;
00074         GeometryPropertyCommand  *lastGeoCommand;
00075         bool isUndoing : 1;
00076         bool slotPropertyChangedEnabled : 1;
00077         bool slotPropertyChanged_addCommandEnabled : 1;
00078 
00079         // helper to change color palette when switching 'enabled' property
00080         QColorGroup* origActiveColors;
00081 
00082         // i18n stuff
00083         QMap<QCString, QString> propCaption;
00084         QMap<QCString, QString> propValCaption;
00085 };
00086 }
00087 
00088 WidgetPropertySet::WidgetPropertySet(QObject *parent)
00089  : QObject(parent, "kfd_widgetPropertySet")
00090 {
00091     d = new WidgetPropertySetPrivate();
00092 //  d->manager = manager;
00093 
00094     connect(&d->set, SIGNAL(propertyChanged(KoProperty::Set&, KoProperty::Property&)),
00095         this, SLOT(slotPropertyChanged(KoProperty::Set&, KoProperty::Property&)));
00096     connect(&d->set, SIGNAL(propertyReset(KoProperty::Set&, KoProperty::Property&)),
00097         this, SLOT(slotPropertyReset(KoProperty::Set&, KoProperty::Property&)));
00098 
00099     initPropertiesDescription();
00100 }
00101 
00102 WidgetPropertySet::~WidgetPropertySet()
00103 {
00104     delete d;
00105 }
00106 
00107 /*FormManager*
00108 WidgetPropertySet::manager()
00109 {
00110     return d->manager;
00111 }*/
00112 
00113 KoProperty::Property&
00114 WidgetPropertySet::operator[](const QCString &name)
00115 {
00116     return d->set[name];
00117 }
00118 
00119 KoProperty::Property&
00120 WidgetPropertySet::property(const QCString &name)
00121 {
00122     return d->set[name];
00123 }
00124 
00125 bool
00126 WidgetPropertySet::contains(const QCString &property)
00127 {
00128     return d->set.contains(property);
00129 }
00130 
00131 KoProperty::Set*
00132 WidgetPropertySet::set()
00133 {
00134     return &(d->set);
00135 }
00136 
00137 void
00138 WidgetPropertySet::clearSet(bool dontSignalShowPropertySet)
00139 {
00140     saveModifiedProperties();
00141 
00142     if (!dontSignalShowPropertySet)
00143         KFormDesigner::FormManager::self()->showPropertySet(0);
00144     d->widgets.clear();
00145     d->lastCommand = 0;
00146     d->lastGeoCommand = 0;
00147     d->properties.clear();
00148     d->set.clear();
00149 
00150     if(!d->widgets.isEmpty())  {
00151         d->widgets.first()->removeEventFilter(this);
00152         disconnect(d->widgets.first(), 0, this, 0);
00153     }
00154 }
00155 
00156 void
00157 WidgetPropertySet::saveModifiedProperties()
00158 {
00159     QWidget * w = d->widgets.first();
00160     if(!w || d->widgets.count() > 1 || !KFormDesigner::FormManager::self()->activeForm() || !KFormDesigner::FormManager::self()->activeForm()->objectTree())
00161             return;
00162     ObjectTreeItem *tree = KFormDesigner::FormManager::self()->activeForm()->objectTree()->lookup(w->name());
00163     if(!tree)
00164         return;
00165 
00166     for(KoProperty::Set::Iterator it(d->set); it.current(); ++it) {
00167         if(it.current()->isModified())
00168             tree->addModifiedProperty(it.current()->name(), it.current()->oldValue());
00169     }
00170 }
00171 
00172 void
00173 WidgetPropertySet::setUndoing(bool isUndoing)
00174 {
00175     d->isUndoing = isUndoing;
00176 }
00177 
00178 bool
00179 WidgetPropertySet::isUndoing()
00180 {
00181     return d->isUndoing;
00182 }
00183 
00185 
00186 void
00187 WidgetPropertySet::setSelectedWidget(QWidget *w, bool add)
00188 {
00189     if(!w) {
00190         clearSet();
00191         return;
00192     }
00193 
00194     // don't add a widget twice
00195     if(d->widgets.contains(QGuardedPtr<QWidget>(w))) {
00196         kdWarning() << "WidgetPropertySet::setSelectedWidget() Widget is already selected" << endl;
00197         return;
00198     }
00199     // if our list is empty,don't use add parameter value
00200     if(d->widgets.count() == 0)
00201         add = false;
00202 
00203     if(add)
00204         addWidget(w);
00205     else {
00206         clearSet(true); //clear but do not reload to avoid blinking
00207         d->widgets.append(QGuardedPtr<QWidget>(w));
00208         createPropertiesForWidget(w);
00209 
00210         w->installEventFilter(this);
00211         connect(w, SIGNAL(destroyed()), this, SLOT(slotWidgetDestroyed()));
00212     }
00213 
00214     KFormDesigner::FormManager::self()->showPropertySet(this, true/*force*/);
00215 }
00216 
00217 void
00218 WidgetPropertySet::addWidget(QWidget *w)
00219 {
00220     d->widgets.append(QGuardedPtr<QWidget>(w));
00221 
00222     // Reset some stuff
00223     d->lastCommand = 0;
00224     d->lastGeoCommand = 0;
00225     d->properties.clear();
00226 
00227     QCString classname;
00228     if(d->widgets.first()->className() == w->className())
00229         classname = d->widgets.first()->className();
00230 
00231     // show only properties shared by widget (properties chosed by factory)
00232     bool isTopLevel = KFormDesigner::FormManager::self()->isTopLevel(w);
00233     for(KoProperty::Set::Iterator it(d->set); it.current(); ++it) {
00234         if(!isPropertyVisible(it.currentKey(), isTopLevel, classname))
00235             d->set[it.currentKey()].setVisible(false);
00236     }
00237 
00238     if (d->widgets.count()>=2) {
00239         //second widget, update metainfo
00240         d->set["this:classString"].setValue(
00241             i18n("Multiple Widgets") + QString(" (%1)").arg(d->widgets.count()) );
00242         d->set["this:iconName"].setValue("multiple_obj");
00243         //name doesn't make sense for now
00244         d->set["name"].setValue("");
00245     }
00246 }
00247 
00248 void
00249 WidgetPropertySet::createPropertiesForWidget(QWidget *w)
00250 {
00251     Form *form;
00252     if (!KFormDesigner::FormManager::self() 
00253         || !(form = KFormDesigner::FormManager::self()->activeForm()) 
00254         || !KFormDesigner::FormManager::self()->activeForm()->objectTree())
00255     {
00256         kdWarning() << "WidgetPropertySet::createPropertiesForWidget() no manager or active form!!!" << endl;
00257         return;
00258     }
00259     ObjectTreeItem *tree = form->objectTree()->lookup(w->name());
00260     if(!tree)
00261         return;
00262 
00263     const QVariantMap* modifiedProperties = tree->modifiedProperties();
00264     QVariantMapConstIterator modifiedPropertiesIt;
00265     bool isTopLevel = KFormDesigner::FormManager::self()->isTopLevel(w);
00266     int count = 0;
00267     KoProperty::Property *newProp = 0;
00268     WidgetInfo *winfo = form->library()->widgetInfoForClassName(w->className());
00269     if (!winfo) {
00270         kdWarning() << "WidgetPropertySet::createPropertiesForWidget() no widget info for class " 
00271             << w->className() << endl;
00272         return;
00273     }
00274 
00275     QStrList pList = w->metaObject()->propertyNames(true);
00276     QStrListIterator it(pList);
00277 
00278     // iterate over the property list, and create Property objects
00279     for(; it.current() != 0; ++it)  {
00280         count = w->metaObject()->findProperty(*it, true);
00281         const QMetaProperty *meta = w->metaObject()->property(count, true);
00282         const char* propertyName = meta->name();
00283 
00284         if(meta->designable(w) && !d->set.contains(propertyName))  {
00286             QString desc( d->propCaption[meta->name()] );
00288             if (desc.isEmpty())  //try to get property description from factory
00289                 desc = form->library()->propertyDescForName(winfo, propertyName);
00290 
00291             modifiedPropertiesIt = modifiedProperties->find(propertyName);
00292             const bool oldValueExists = modifiedPropertiesIt!=modifiedProperties->constEnd();
00293 
00294             if(meta->isEnumType()) {
00295                 if(qstrcmp(propertyName, "alignment") == 0)  {
00296                     createAlignProperty(meta, w);
00297                     continue;
00298                 }
00299 
00300                 QStringList keys = QStringList::fromStrList( meta->enumKeys() );
00301                 newProp = new KoProperty::Property(propertyName, createValueList(winfo, keys),
00302                     /* assign current or older value */
00303                     oldValueExists ? modifiedPropertiesIt.data() : 
00304                         meta->valueToKey( w->property(propertyName).toInt() ), 
00305                     desc, desc );
00306                 //now set current value, so the old one is stored as old
00307                 if (oldValueExists) {
00308                     newProp->setValue( meta->valueToKey( w->property(propertyName).toInt() ) );
00309                 }
00310             }
00311             else {
00312                 newProp = new KoProperty::Property(propertyName, 
00313                     /* assign current or older value */
00314                     oldValueExists ? modifiedPropertiesIt.data() : w->property(propertyName), 
00315                     desc, desc, winfo->customTypeForProperty(propertyName));
00316                 //now set current value, so the old one is stored as old
00317                 if (oldValueExists) {
00318                     newProp->setValue( w->property(propertyName) );
00319                 }
00320             }
00321 
00322             d->set.addProperty(newProp);
00323             if(!isPropertyVisible(propertyName, isTopLevel))
00324                 newProp->setVisible(false);
00326             if(newProp->type() == 0) // invalid type == null pixmap ?
00327                 newProp->setType(KoProperty::Pixmap);
00328         }
00329 
00330 //      if(0==qstrcmp(propertyName, "name"))
00331 //          (*this)["name"].setAutoSync(0); // name should be updated only when pressing Enter
00332 
00333         // \todo js what does this mean? why do you use WidgetInfo and not WidgetLibrary
00334         /*if (winfo) {
00335             tristate autoSync = winfo->autoSyncForProperty( propertyName );
00336             if (! ~autoSync)
00337                 d->set[propertyName].setAutoSync( autoSync );
00338         }*/
00339 
00340         // update the Property.oldValue() and isModified() using the value stored in the ObjectTreeItem
00341         updatePropertyValue(tree, propertyName);
00342     }
00343 
00344     (*this)["name"].setAutoSync(false); // name should be updated only when pressing Enter
00345     (*this)["enabled"].setValue( QVariant(tree->isEnabled(), 3));
00346 
00347     if (winfo) {
00348         form->library()->setPropertyOptions(*this, *winfo, w);
00349         //add meta-information
00350         d->set.addProperty( newProp = new KoProperty::Property("this:classString", winfo->name()) );
00351         newProp->setVisible(false);
00352         d->set.addProperty( newProp = new KoProperty::Property("this:iconName", winfo->pixmap()) );
00353         newProp->setVisible(false);
00354         d->set.addProperty( newProp = new KoProperty::Property("this:iconName", winfo->pixmap()) );
00355         newProp->setVisible(false);
00356     }
00357     d->set.addProperty( newProp = new KoProperty::Property("this:className", w->className()) ); 
00358     newProp->setVisible(false);
00359 
00373     if(KFormDesigner::FormManager::self()->activeForm() && tree->container()) // we are a container -> layout property
00374         createLayoutProperty(tree);
00375 }
00376 
00377 void
00378 WidgetPropertySet::updatePropertyValue(ObjectTreeItem *tree, const char *property)
00379 {
00380     if (!d->set.contains(property))
00381         return;
00382     KoProperty::Property p = d->set[property];
00383 
00385     QMap<QString, QVariant>::ConstIterator it( tree->modifiedProperties()->find(property) );
00386     if (it != tree->modifiedProperties()->constEnd()) {
00387         blockSignals(true);
00388         p.setValue(it.data(), false );
00389         p.setValue(p.value(), true);
00390         blockSignals(false);
00391     }
00392 }
00393 
00394 bool
00395 WidgetPropertySet::isPropertyVisible(const QCString &property, bool isTopLevel, const QCString &classname)
00396 {
00397     const bool multiple = d->widgets.count() >= 2;
00398     if(multiple && classname.isEmpty())
00399         return false;
00400 /* moved to WidgetLibrary::isPropertyVisible()
00401     if(d->widgets.count() < 2)
00402     {
00403         if(d->properties.isEmpty() && !isTopLevel)
00404             d->properties << "caption" << "icon" << "sizeIncrement" << "iconText";
00405          // don't show these properties for a non-toplevel widget
00406 
00407         if(! (d->properties.grep(property)).isEmpty() )
00408             return false;
00409     }
00410     else
00411     {
00412         if(classname.isEmpty())
00413             return false;
00414 
00415         if(d->properties.isEmpty())  {
00416             d->properties << "font" << "paletteBackgroundColor" << "enabled" << "paletteForegroundColor"
00417                << "cursor" << "paletteBackgroundPixmap";
00418         } // properties always shown in multiple mode
00419         if(! (d->properties.grep(property)).isEmpty() )
00420             return true;
00421     }
00422 */
00423 
00424 //  return KFormDesigner::FormManager::self()->lib()->isPropertyVisible(d->widgets.first()->className(), d->widgets.first(),
00425     return KFormDesigner::FormManager::self()->activeForm()->library()->isPropertyVisible(
00426         d->widgets.first()->className(), d->widgets.first(), property, multiple, isTopLevel);
00427 }
00428 
00430 
00431 void
00432 WidgetPropertySet::slotPropertyChanged(KoProperty::Set& set, KoProperty::Property& p)
00433 {
00434     Q_UNUSED( set );
00435 
00436     if(!d->slotPropertyChangedEnabled || !KFormDesigner::FormManager::self() || !KFormDesigner::FormManager::self()->activeForm()
00437         || ! KFormDesigner::FormManager::self()->activeForm()->objectTree())
00438         return;
00439 
00440     QCString property = p.name();
00441     if (0==property.find("this:"))
00442         return; //starts with magical prefix: it's meta prop.
00443 
00444     QVariant value = p.value();
00445 
00446     // check if the name is valid (ie is correct identifier) and there is no name conflict
00447     if(property == "name") {
00448         if(d->widgets.count()!=1)
00449             return;
00450         if(!isNameValid(value.toString()))
00451             return;
00452     }
00453     // a widget with a background pixmap should have its own origin
00454     else if(property == "paletteBackgroundPixmap") {
00455         d->set["backgroundOrigin"] = "WidgetOrigin";
00456     //else if(property == "signals")
00457     //  return;
00458     // special types of properties handled separately
00459     } else if((property == "hAlign") || (property == "vAlign") || (property == "wordbreak")) {
00460         saveAlignProperty(property);
00461         return;
00462     }
00463     else if((property == "layout") || (property == "layoutMargin") || (property == "layoutSpacing")) {
00464         saveLayoutProperty(property, value);
00465         return;
00466     }
00467     // we cannot really disable the widget, we just change its color palette
00468     else if(property == "enabled")  {
00469         saveEnabledProperty(value.toBool());
00470         return;
00471     }
00472 
00473      // make sure we are not already undoing -> avoid recursion
00474     if(d->isUndoing && !KFormDesigner::FormManager::self()->isRedoing())
00475         return;
00476 
00477     const bool alterLastCommand = d->lastCommand && d->lastCommand->property() == property;
00478 
00479     if(d->widgets.count() == 1) // one widget selected
00480     {
00481         // If the last command is the same, we just change its value
00482         if(alterLastCommand && !KFormDesigner::FormManager::self()->isRedoing())
00483             d->lastCommand->setValue(value);
00484         else  {
00485 //          if(m_widgets.first() && ((m_widgets.first() != m_manager->activeForm()->widget()) || (property != "geometry"))) {
00486             if (d->slotPropertyChanged_addCommandEnabled && !KFormDesigner::FormManager::self()->isRedoing()) {
00487                 d->lastCommand = new PropertyCommand(this, d->widgets.first()->name(),
00488                         d->widgets.first()->property(property), value, property);
00489                 KFormDesigner::FormManager::self()->activeForm()->addCommand(d->lastCommand, false);
00490             }
00491 
00492             // If the property is changed, we add it in ObjectTreeItem modifProp
00493             ObjectTreeItem *tree = KFormDesigner::FormManager::self()->activeForm()->objectTree()->lookup(d->widgets.first()->name());
00494             if (tree && p.isModified())
00495                 tree->addModifiedProperty(property, d->widgets.first()->property(property));
00496         }
00497 
00498             if(property == "name")
00499                 emit widgetNameChanged(d->widgets.first()->name(), p.value().toCString());
00500             d->widgets.first()->setProperty(property, value);
00501             emit widgetPropertyChanged(d->widgets.first(), property, value);
00502     }
00503     else
00504     {
00505         if(alterLastCommand && !KFormDesigner::FormManager::self()->isRedoing())
00506             d->lastCommand->setValue(value);
00507         else {
00508             if (d->slotPropertyChanged_addCommandEnabled && !KFormDesigner::FormManager::self()->isRedoing()) {
00509                 // We store old values for each widget
00510                 QMap<QCString, QVariant> list;
00511     //          for(QWidget *w = d->widgets.first(); w; w = d->widgets.next())
00512                 foreach(QGuardedWidgetList::ConstIterator, it, d->widgets)
00513                     list.insert((*it)->name(), (*it)->property(property));
00514 
00515                 d->lastCommand = new PropertyCommand(this, list, value, property);
00516                 KFormDesigner::FormManager::self()->activeForm()->addCommand(d->lastCommand, false);
00517             }
00518         }
00519 
00520 //          for(QWidget *w = d->widgets.first(); w; w = d->widgets.next())
00521         foreach(QGuardedWidgetList::ConstIterator, it, d->widgets) {
00522             if (!alterLastCommand) {
00523                 ObjectTreeItem *tree = KFormDesigner::FormManager::self()->activeForm()->objectTree()->lookup((*it)->name());
00524                 if(tree && p.isModified())
00525                     tree->addModifiedProperty(property, (*it)->property(property));
00526             }
00527             (*it)->setProperty(property, value);
00528             emit widgetPropertyChanged((*it), property, value);
00529         }
00530     }
00531 }
00532 
00533 void
00534 WidgetPropertySet::createPropertyCommandsInDesignMode(QWidget* widget, 
00535     const QMap<QCString, QVariant> &propValues, CommandGroup *group, bool addToActiveForm,
00536     bool execFlagForSubCommands)
00537 {
00538     if (!widget || propValues.isEmpty())
00539         return;
00540     
00541     //is this widget selected? (if so, use property system)
00542     const bool widgetIsSelected = KFormDesigner::FormManager::self()->activeForm()->selectedWidget() == widget;
00543 
00544     d->slotPropertyChanged_addCommandEnabled = false;
00545     QMap<QCString, QVariant>::ConstIterator endIt = propValues.constEnd();
00546 //  CommandGroup *group = new CommandGroup(commandName);
00547     for(QMap<QCString, QVariant>::ConstIterator it = propValues.constBegin(); it != endIt; ++it)
00548     {
00549         if (!d->set.contains(it.key())) {
00550             kdWarning() << "WidgetPropertySet::createPropertyCommandsInDesignMode(): \"" <<it.key()<<"\" property not found"<<endl;
00551             continue;
00552         }
00553         PropertyCommand *subCommand = new PropertyCommand(this, widget->name(),
00554             widget->property(it.key()), it.data(), it.key());
00555         group->addCommand( subCommand, execFlagForSubCommands);
00556         if (widgetIsSelected) {
00557             d->set[it.key()].setValue(it.data());
00558         }
00559         else {
00560             if (-1!=widget->metaObject()->findProperty(it.key(), true) && widget->property(it.key())!=it.data()) {
00561                 ObjectTreeItem *tree = KFormDesigner::FormManager::self()->activeForm()->objectTree()->lookup(widget->name());
00562                 if (tree)
00563                     tree->addModifiedProperty(it.key(), widget->property(it.key()));
00564                 widget->setProperty(it.key(), it.data());
00565                 emit widgetPropertyChanged(widget, it.key(), it.data());
00566             }
00567         }
00568     }
00569     d->lastCommand = 0;
00570     if (addToActiveForm)
00571         KFormDesigner::FormManager::self()->activeForm()->addCommand(group, false/*no exec*/);
00572     d->slotPropertyChanged_addCommandEnabled = true;
00573 //  }
00574 }
00575 
00577 void
00578 WidgetPropertySet::saveEnabledProperty(bool value)
00579 {
00580 //  for(QWidget *w = d->widgets.first(); w; w = d->widgets.next()) {
00581     foreach(QGuardedWidgetList::ConstIterator, it, d->widgets) {
00582         ObjectTreeItem *tree = KFormDesigner::FormManager::self()->activeForm()->objectTree()
00583             ->lookup((*it)->name());
00584         if(tree->isEnabled() == value)
00585             continue;
00586 
00587         QPalette p( (*it)->palette() );
00588         if (!d->origActiveColors)
00589             d->origActiveColors = new QColorGroup( p.active() );
00590         if (value) {
00591             if (d->origActiveColors)
00592                 p.setActive( *d->origActiveColors ); //revert
00593         }
00594         else {
00595             QColorGroup cg = p.disabled();
00596             //also make base color a bit disabled-like
00597             cg.setColor(QColorGroup::Base, cg.color(QColorGroup::Background));
00598             p.setActive(cg);
00599         }
00600         (*it)->setPalette(p);
00601 
00602         tree->setEnabled(value);
00603         emit widgetPropertyChanged((*it), "enabled", QVariant(value, 3));
00604     }
00605 }
00606 
00607 bool
00608 WidgetPropertySet::isNameValid(const QString &name)
00609 {
00611     QWidget *w = d->widgets.first();
00612     //also update widget's name in QObject member
00613     if (!KexiUtils::isIdentifier(name)) {
00614         KMessageBox::sorry(KFormDesigner::FormManager::self()->activeForm()->widget(),
00615             i18n("Could not rename widget \"%1\" to \"%2\" because "
00616             "\"%3\" is not a valid name (identifier) for a widget.\n")
00617             .arg(w->name()).arg(name).arg(name));
00618         d->slotPropertyChangedEnabled = false;
00619         d->set["name"].resetValue();
00620         d->slotPropertyChangedEnabled = true;
00621         return false;
00622     }
00623 
00624     if (KFormDesigner::FormManager::self()->activeForm()->objectTree()->lookup(name)) {
00625         KMessageBox::sorry( KFormDesigner::FormManager::self()->activeForm()->widget(),
00626             i18n("Could not rename widget \"%1\" to \"%2\" "
00627             "because a widget with the name \"%3\" already exists.\n")
00628             .arg(w->name()).arg(name).arg(name));
00629         d->slotPropertyChangedEnabled = false;
00630         d->set["name"].resetValue();
00631         d->slotPropertyChangedEnabled = true;
00632         return false;
00633     }
00634 
00635     return true; //ie name is correct
00636 }
00637 
00638 void
00639 WidgetPropertySet::slotPropertyReset(KoProperty::Set& set, KoProperty::Property& property)
00640 {
00641     Q_UNUSED( set );
00642 
00643     if(d->widgets.count() < 2)
00644         return;
00645 
00646     // We use the old value in modifProp for each widget
00647 //  for(QWidget *w = d->widgets.first(); w; w = d->widgets.next())  {
00648     foreach(QGuardedWidgetList::ConstIterator, it, d->widgets) {
00649         ObjectTreeItem *tree = KFormDesigner::FormManager::self()->activeForm()->objectTree()->lookup((*it)->name());
00650         if(tree->modifiedProperties()->contains(property.name()))
00651             (*it)->setProperty(property.name(), tree->modifiedProperties()->find(property.name()).data());
00652     }
00653 }
00654 
00655 void
00656 WidgetPropertySet::slotWidgetDestroyed()
00657 {
00658 //  if(d->widgets.contains(QGuardedPtr<const QWidget>( dynamic_cast<const QWidget*>(sender()) ))) {
00659     //only clear this set if it contains the destroyed widget
00660     foreach(QGuardedWidgetList::ConstIterator, it, d->widgets) {
00661         if (dynamic_cast<const QWidget*>(sender()) == *it) {
00662             clearSet();
00663             break;
00664         }
00665     }
00666 }
00667 
00668 bool
00669 WidgetPropertySet::eventFilter(QObject *o, QEvent *ev)
00670 {
00671     if(d->widgets.count() > 0 && o == d->widgets.first() && d->widgets.count() < 2)
00672     {
00673         if((ev->type() == QEvent::Resize) || (ev->type() == QEvent::Move))  {
00674             if(!d->set.contains("geometry"))
00675                 return false;
00676             if(d->set["geometry"].value() == o->property("geometry")) // to avoid infinite recursion
00677                 return false;
00678 
00679             d->set["geometry"] = static_cast<QWidget*>(o)->geometry();
00680         }
00681     }
00682     else if(d->widgets.count() > 1 && ev->type() == QEvent::Move) // the widget is being moved, we update the property
00683     {
00684         if(d->isUndoing)
00685             return false;
00686 
00687         if(d->lastGeoCommand)
00688             d->lastGeoCommand->setPos(static_cast<QMoveEvent*>(ev)->pos());
00689         else  {
00690             QStringList list;
00691             foreach(QGuardedWidgetList::ConstIterator, it, d->widgets)
00692                 list.append((*it)->name());
00693 
00694             d->lastGeoCommand = new GeometryPropertyCommand(this, list, static_cast<QMoveEvent*>(ev)->oldPos());
00695             if (KFormDesigner::FormManager::self()->activeForm())
00696                 KFormDesigner::FormManager::self()->activeForm()->addCommand(d->lastGeoCommand, false);
00697         }
00698     }
00699 
00700     return false;
00701 }
00702 
00703 // Alignment-related functions /////////////////////////////
00704 
00705 void
00706 WidgetPropertySet::createAlignProperty(const QMetaProperty *meta, QWidget *obj)
00707 {
00708     if (!KFormDesigner::FormManager::self()->activeForm() || !KFormDesigner::FormManager::self()->activeForm()->objectTree())
00709         return;
00710 
00711     QStringList list;
00712     QString value;
00713     const int alignment = obj->property("alignment").toInt();
00714     QStringList keys = QStringList::fromStrList( meta->valueToKeys(alignment) );
00715 
00716     QStrList *enumKeys = new QStrList(meta->enumKeys());
00717     QStringList possibleValues = QStringList::fromStrList(*enumKeys);
00718     delete enumKeys;
00719 
00720     ObjectTreeItem *tree = KFormDesigner::FormManager::self()->activeForm()->objectTree()->lookup(obj->name());
00721     bool isTopLevel = KFormDesigner::FormManager::self()->isTopLevel(obj);
00722 
00723     if(!possibleValues.grep("AlignHCenter").empty())  {
00724         // Create the horizontal alignment property
00725         if(!keys.grep("AlignHCenter").isEmpty())
00726             value = "AlignHCenter";
00727         else if(!keys.grep("AlignRight").isEmpty())
00728             value = "AlignRight";
00729         else if(!keys.grep("AlignLeft").isEmpty())
00730             value = "AlignLeft";
00731         else if(!keys.grep("AlignJustify").isEmpty())
00732             value = "AlignJustify";
00733         else
00734             value = "AlignAuto";
00735 
00736         list << "AlignAuto" << "AlignLeft" << "AlignRight" << "AlignHCenter" << "AlignJustify";
00737         KoProperty::Property *p = new KoProperty::Property("hAlign", createValueList(0, list), value,
00738             i18n("Translators: please keep this string short (less than 20 chars)", "Hor. Alignment"),
00739             i18n("Horizontal Alignment"));
00740         d->set.addProperty(p);
00741         if(!isPropertyVisible(p->name(), isTopLevel)) {
00742             p->setVisible(false);
00743         }
00744         updatePropertyValue(tree, "hAlign");
00745         list.clear();
00746     }
00747 
00748     if(!possibleValues.grep("AlignTop").empty())
00749     {
00750         // Create the ver alignment property
00751         if(!keys.grep("AlignTop").empty())
00752             value = "AlignTop";
00753         else if(!keys.grep("AlignBottom").empty())
00754             value = "AlignBottom";
00755         else
00756             value = "AlignVCenter";
00757 
00758         list << "AlignTop" << "AlignVCenter" << "AlignBottom";
00759         KoProperty::Property *p = new KoProperty::Property("vAlign", createValueList(0, list), value,
00760             i18n("Translators: please keep this string short (less than 20 chars)", "Ver. Alignment"),
00761             i18n("Vertical Alignment"));
00762         d->set.addProperty(p);
00763         if(!isPropertyVisible(p->name(), isTopLevel)) {
00764             p->setVisible(false);
00765         }
00766         updatePropertyValue(tree, "vAlign");
00767     }
00768 
00769     if(!possibleValues.grep("WordBreak").empty()
00770       && !obj->inherits("QLineEdit") /* QLineEdit doesn't support 'word break' is this generic enough?*/
00771     ) {
00772         // Create the wordbreak property
00773         KoProperty::Property *p = new KoProperty::Property("wordbreak", 
00774             QVariant(alignment & Qt::WordBreak, 3), i18n("Word Break"), i18n("Word Break") );
00775         d->set.addProperty(p);
00776         updatePropertyValue(tree, "wordbreak");
00777         if(!isPropertyVisible(p->name(), isTopLevel)) {
00778             p->setVisible(false);
00779         }
00780     }
00781 }
00782 
00783 void
00784 WidgetPropertySet::saveAlignProperty(const QString &property)
00785 {
00786     if (!KFormDesigner::FormManager::self()->activeForm())
00787         return;
00788 
00789     QStrList list;
00790     if( d->set.contains("hAlign") )
00791         list.append( d->set["hAlign"].value().toCString() );
00792     if( d->set.contains("vAlign") )
00793         list.append( d->set["vAlign"].value().toCString() );
00794     if( d->set.contains("wordbreak") && d->set["wordbreak"].value().toBool() )
00795         list.append("WordBreak");
00796 
00797     int count = d->widgets.first()->metaObject()->findProperty("alignment", true);
00798     const QMetaProperty *meta = d->widgets.first()->metaObject()->property(count, true);
00799     d->widgets.first()->setProperty("alignment", meta->keysToValue(list));
00800 
00801 
00802     ObjectTreeItem *tree = KFormDesigner::FormManager::self()->activeForm()->objectTree()->lookup(d->widgets.first()->name());
00803     if(tree && d->set[property.latin1()].isModified())
00804         tree->addModifiedProperty(property.latin1(), d->set[property.latin1()].oldValue());
00805 
00806     if(d->isUndoing)
00807         return;
00808 
00809     if(d->lastCommand && d->lastCommand->property() == "alignment")
00810         d->lastCommand->setValue(meta->keysToValue(list));
00811     else {
00812         d->lastCommand = new PropertyCommand(this, d->widgets.first()->name(),
00813             d->widgets.first()->property("alignment"), meta->keysToValue(list), "alignment");
00814         KFormDesigner::FormManager::self()->activeForm()->addCommand(d->lastCommand, false);
00815     }
00816 }
00817 
00818 // Layout-related functions  //////////////////////////
00819 
00820 void
00821 WidgetPropertySet::createLayoutProperty(ObjectTreeItem *item)
00822 {
00823     Container *container = item->container();
00824     if (!container || !KFormDesigner::FormManager::self()->activeForm() ||
00825         !KFormDesigner::FormManager::self()->activeForm()->objectTree() || !container->widget())
00826         return;
00827     // special containers have no 'layout' property, as it should not be changed
00828     QCString className = container->widget()->className();
00829     if((className == "HBox") || (className == "VBox") || (className == "Grid"))
00830         return;
00831 
00832     QStringList list;
00833     QString value = Container::layoutTypeToString(container->layoutType());
00834 
00835     list << "NoLayout" << "HBox" << "VBox" << "Grid" << "HFlow" << "VFlow";
00836 
00837     KoProperty::Property *p = new KoProperty::Property("layout", createValueList(0, list), value,
00838         i18n("Container's Layout"), i18n("Container's Layout"));
00839     p->setVisible( container->form()->library()->advancedPropertiesVisible() );
00840     d->set.addProperty(p);
00841 
00842     updatePropertyValue(item, "layout");
00843 
00844     p = new KoProperty::Property("layoutMargin", container->layoutMargin(), i18n("Layout Margin"), i18n("Layout Margin"));
00845     d->set.addProperty(p);
00846     updatePropertyValue(item, "layoutMargin");
00847     if(container->layoutType() == Container::NoLayout)
00848         p->setVisible(false);
00849 
00850     p = new KoProperty::Property("layoutSpacing", container->layoutSpacing(), 
00851         i18n("Layout Spacing"), i18n("Layout Spacing"));
00852     d->set.addProperty(p);
00853     updatePropertyValue(item, "layoutSpacing");
00854     if(container->layoutType() == Container::NoLayout)
00855         p->setVisible(false);
00856 
00857 }
00858 
00859 void
00860 WidgetPropertySet::saveLayoutProperty(const QString &prop, const QVariant &value)
00861 {
00862     Container *container=0;
00863     if(!KFormDesigner::FormManager::self()->activeForm() || !KFormDesigner::FormManager::self()->activeForm()->objectTree())
00864         return;
00865     ObjectTreeItem *item = KFormDesigner::FormManager::self()->activeForm()->objectTree()->lookup(d->widgets.first()->name());
00866     if(!item)
00867         return;
00868     container = item->container();
00869 
00870     if(prop == "layout") {
00871         Container::LayoutType type = Container::stringToLayoutType(value.toString());
00872 
00873         if(d->lastCommand && d->lastCommand->property() == "layout" && !d->isUndoing)
00874             d->lastCommand->setValue(value);
00875         else if(!d->isUndoing)  {
00876             d->lastCommand = new LayoutPropertyCommand(this, d->widgets.first()->name(),
00877                 d->set["layout"].oldValue(), value);
00878             KFormDesigner::FormManager::self()->activeForm()->addCommand(d->lastCommand, false);
00879         }
00880 
00881         container->setLayout(type);
00882         bool show = (type != Container::NoLayout);
00883         if(show != d->set["layoutMargin"].isVisible())  {
00884             d->set["layoutMargin"].setVisible(show);
00885             d->set["layoutSpacing"].setVisible(show);
00886             KFormDesigner::FormManager::self()->showPropertySet(this, true/*force*/);
00887         }
00888         return;
00889     }
00890 
00891     if(prop == "layoutMargin" && container->layout()) {
00892         container->setLayoutMargin(value.toInt());
00893         container->layout()->setMargin(value.toInt());
00894     }
00895     else if(prop == "layoutSpacing" && container->layout())  {
00896         container->setLayoutSpacing(value.toInt());
00897         container->layout()->setSpacing(value.toInt());
00898     }
00899 
00900     ObjectTreeItem *tree = KFormDesigner::FormManager::self()->activeForm()->objectTree()->lookup(d->widgets.first()->name());
00901     if(tree && d->set[ prop.latin1() ].isModified())
00902         tree->addModifiedProperty(prop.latin1(), d->set[prop.latin1()].oldValue());
00903 
00904     if(d->isUndoing)
00905         return;
00906 
00907     if(d->lastCommand && (QString(d->lastCommand->property()) == prop))
00908         d->lastCommand->setValue(value);
00909     else  {
00910         d->lastCommand = new PropertyCommand(this, d->widgets.first()->name(),
00911             d->set[ prop.latin1() ].oldValue(), value, prop.latin1());
00912         KFormDesigner::FormManager::self()->activeForm()->addCommand(d->lastCommand, false);
00913     }
00914 }
00915 
00916 
00917 
00919 
00920 void
00921 WidgetPropertySet::initPropertiesDescription()
00922 {
00925     d->propCaption["name"] = i18n("Name");
00926     d->propCaption["caption"] = i18n("Caption");
00927     d->propCaption["text"] = i18n("Text");
00928     d->propCaption["paletteBackgroundPixmap"] = i18n("Background Pixmap");
00929     d->propCaption["enabled"] = i18n("Enabled");
00930     d->propCaption["geometry"] = i18n("Geometry");
00931     d->propCaption["sizePolicy"] = i18n("Size Policy");
00932     d->propCaption["minimumSize"] = i18n("Minimum Size");
00933     d->propCaption["maximumSize"] = i18n("Maximum Size");
00934     d->propCaption["font"] = i18n("Font");
00935     d->propCaption["cursor"] = i18n("Cursor");
00936     d->propCaption["paletteForegroundColor"] = i18n("Foreground Color");
00937     d->propCaption["paletteBackgroundColor"] = i18n("Background Color");
00938     d->propCaption["focusPolicy"] = i18n("Focus Policy");
00939     d->propCaption["margin"] = i18n("Margin");
00940     d->propCaption["readOnly"] = i18n("Read Only");
00941     //any QFrame
00942     d->propCaption["frame"] = i18n("Frame");
00943     d->propCaption["lineWidth"] = i18n("Frame Width");
00944     d->propCaption["midLineWidth"] = i18n("Mid Frame Width");
00945     d->propCaption["frameShape"] = i18n("Frame Shape");
00946     d->propCaption["frameShadow"] = i18n("Frame Shadow");
00947     //any QScrollbar
00948     d->propCaption["vScrollBarMode"] = i18n("Vertical ScrollBar");
00949     d->propCaption["hScrollBarMode"] = i18n("Horizontal ScrollBar");
00950 
00951     d->propValCaption["NoBackground"] = i18n("No Background");
00952     d->propValCaption["PaletteForeground"] = i18n("Palette Foreground");
00953     d->propValCaption["AutoText"] = i18n("Auto (HINT: for AutoText)", "Auto");
00954 
00955     d->propValCaption["AlignAuto"] = i18n("Auto (HINT: for Align)", "Auto");
00956     d->propValCaption["AlignLeft"] = i18n("Left (HINT: for Align)", "Left");
00957     d->propValCaption["AlignRight"] = i18n("Right (HINT: for Align)", "Right");
00958     d->propValCaption["AlignHCenter"] = i18n("Center (HINT: for Align)", "Center");
00959     d->propValCaption["AlignJustify"] = i18n("Justify (HINT: for Align)", "Justify");
00960     d->propValCaption["AlignVCenter"] = i18n("Center (HINT: for Align)", "Center");
00961     d->propValCaption["AlignTop"] = i18n("Top (HINT: for Align)", "Top");
00962     d->propValCaption["AlignBottom"] = i18n("Bottom (HINT: for Align)", "Bottom");
00963 
00964     d->propValCaption["NoFrame"] = i18n("No Frame (HINT: for Frame Shape)", "No Frame");
00965     d->propValCaption["Box"] = i18n("Box (HINT: for Frame Shape)", "Box");
00966     d->propValCaption["Panel"] = i18n("Panel (HINT: for Frame Shape)", "Panel");
00967     d->propValCaption["WinPanel"] = i18n("Windows Panel (HINT: for Frame Shape)", "Windows Panel");
00968     d->propValCaption["HLine"] = i18n("Horiz. Line (HINT: for Frame Shape)", "Horiz. Line");
00969     d->propValCaption["VLine"] = i18n("Vertical Line (HINT: for Frame Shape)", "Vertical Line");
00970     d->propValCaption["StyledPanel"] = i18n("Styled (HINT: for Frame Shape)", "Styled");
00971     d->propValCaption["PopupPanel"] = i18n("Popup (HINT: for Frame Shape)", "Popup");
00972     d->propValCaption["MenuBarPanel"] = i18n("Menu Bar (HINT: for Frame Shape)", "Menu Bar");
00973     d->propValCaption["ToolBarPanel"] = i18n("Toolbar (HINT: for Frame Shape)", "Toolbar");
00974     d->propValCaption["LineEditPanel"] = i18n("Text Box (HINT: for Frame Shape)", "Text Box");
00975     d->propValCaption["TabWidgetPanel"] = i18n("Tab Widget (HINT: for Frame Shape)", "Tab Widget");
00976     d->propValCaption["GroupBoxPanel"] = i18n("Group Box (HINT: for Frame Shape)", "Group Box");
00977 
00978     d->propValCaption["Plain"] = i18n("Plain (HINT: for Frame Shadow)", "Plain");
00979     d->propValCaption["Raised"] = i18n("Raised (HINT: for Frame Shadow)", "Raised");
00980     d->propValCaption["Sunken"] = i18n("Sunken (HINT: for Frame Shadow)", "Sunken");
00981     d->propValCaption["MShadow"] = i18n("for Frame Shadow", "Internal");
00982 
00983     d->propValCaption["NoFocus"] = i18n("No Focus (HINT: for Focus)", "No Focus");
00984     d->propValCaption["TabFocus"] = i18n("Tab (HINT: for Focus)", "Tab");
00985     d->propValCaption["ClickFocus"] = i18n("Click (HINT: for Focus)", "Click");
00986     d->propValCaption["StrongFocus"] = i18n("Tab/Click (HINT: for Focus)", "Tab/Click");
00987     d->propValCaption["WheelFocus"] = i18n("Tab/Click/MouseWheel (HINT: for Focus)", "Tab/Click/MouseWheel");
00988 
00989     d->propValCaption["Auto"] = i18n("Auto");
00990     d->propValCaption["AlwaysOff"] = i18n("Always Off");
00991     d->propValCaption["AlwaysOn"] = i18n("Always On");
00992 
00993     //orientation
00994     d->propValCaption["Horizontal"] = i18n("Horizontal");
00995     d->propValCaption["Vertical"] = i18n("Vertical");
00996 }
00997 
00998 QString
00999 WidgetPropertySet::propertyCaption(const QCString &name)
01000 {
01001     return d->propCaption[name];
01002 }
01003 
01004 QString
01005 WidgetPropertySet::valueCaption(const QCString &name)
01006 {
01007     return d->propValCaption[name];
01008 }
01009 
01010 KoProperty::Property::ListData*
01011 WidgetPropertySet::createValueList(WidgetInfo *winfo, const QStringList &list)
01012 {
01013 //  QMap <QString, QVariant> map;
01014     QStringList names;
01015     QStringList::ConstIterator endIt = list.end();
01016     for(QStringList::ConstIterator it = list.begin(); it != endIt; ++it) {
01017         QString n( d->propValCaption[ (*it).latin1() ] );
01018         if (n.isEmpty()) { //try within factory and (maybe) parent factory
01019             if (winfo)
01020                 n = KFormDesigner::FormManager::self()->activeForm()->library()->propertyDescForValue( winfo, (*it).latin1() );
01021             if (n.isEmpty())
01022                 names.append( *it ); //untranslated
01023 //              map.insert(*it, (*it).latin1()); //untranslated
01024             else
01025                 names.append( n );
01026 //              map.insert(*it, n);
01027         }
01028         else
01029             names.append( n );
01030 //          map.insert(*it, n);
01031     }
01032     return new KoProperty::Property::ListData(list, names);
01033 }
01034 
01035 void
01036 WidgetPropertySet::addPropertyCaption(const QCString &property, const QString &caption)
01037 {
01038     if(!d->propCaption.contains(property))
01039         d->propCaption[property] = caption;
01040 }
01041 
01042 void
01043 WidgetPropertySet::addValueCaption(const QCString &value, const QString &caption)
01044 {
01045     if(!d->propValCaption.contains(value))
01046         d->propValCaption[value] = caption;
01047 }
01048 
01049 #include "widgetpropertyset.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys