lib

property.cpp

00001 /* This file is part of the KDE project
00002    Copyright (C) 2004 Cedric Pasteur <cedric.pasteur@free.fr>
00003    Copyright (C) 2004 Alexander Dymo <cloudtemple@mskat.net>
00004    Copyright (C) 2004-2005 Jaroslaw Staniek <js@iidea.pl>
00005 
00006    This library is free software; you can redistribute it and/or
00007    modify it under the terms of the GNU Library General Public
00008    License as published by the Free Software Foundation; either
00009    version 2 of the License, or (at your option) any later version.
00010 
00011    This library is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014    Library General Public License for more details.
00015 
00016    You should have received a copy of the GNU Library General Public License
00017    along with this library; see the file COPYING.LIB.  If not, write to
00018    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00019  * Boston, MA 02110-1301, USA.
00020 */
00021 
00022 #include "property.h"
00023 #include "customproperty.h"
00024 #include "set.h"
00025 #include "factory.h"
00026 
00027 #ifndef QT_ONLY
00028 #include <kdebug.h>
00029 #endif
00030 
00031 #include <qobject.h>
00032 #include <qptrdict.h>
00033 #include <qasciidict.h>
00034 #include <qguardedptr.h>
00035 
00036 namespace KoProperty {
00037 
00038 QT_STATIC_CONST_IMPL Property Property::null;
00039 
00041 class PropertyPrivate
00042 {
00043     public:
00044         PropertyPrivate()
00045         : caption(0), listData(0), changed(false), storable(true), 
00046          readOnly(false), visible(true),
00047          autosync(-1), custom(0), useCustomProperty(true),
00048          sets(0), parent(0), children(0), relatedProperties(0),
00049          sortingKey(0)
00050         {
00051         }
00052 
00053         inline void setCaptionForDisplaying(const QString& captionForDisplaying)
00054         {
00055             delete caption;
00056             if (captionForDisplaying.simplifyWhiteSpace()!=captionForDisplaying)
00057                 caption = new QString(captionForDisplaying.simplifyWhiteSpace());
00058             else
00059                 caption = 0;
00060             this->captionForDisplaying = captionForDisplaying;
00061         }
00062 
00063         ~PropertyPrivate()
00064         {
00065             delete caption;
00066             caption = 0;
00067             delete children;
00068             delete relatedProperties;
00069             delete custom;
00070             delete sets;
00071         }
00072 
00073     int type;
00074     QCString name;
00075     QString captionForDisplaying;
00076     QString* caption;
00077     QString description;
00078     QVariant value;
00079     QVariant oldValue;
00081     Property::ListData* listData;
00082 //  QMap<QString, QVariant> *valueList;
00083     QString icon;
00084 
00085     bool changed : 1;
00086     bool storable : 1;
00087     bool readOnly : 1;
00088     bool visible : 1;
00089     int autosync;
00090     QMap<QCString, QVariant> options;
00091 
00092     CustomProperty *custom;
00094     bool useCustomProperty;
00095 
00097     QGuardedPtr<Set> set;
00099     QPtrDict< QGuardedPtr<Set> > *sets;
00100 //  QValueList<Set*>  sets;
00101 
00102     Property  *parent;
00103     QValueList<Property*>  *children;
00105     QValueList<Property*>  *relatedProperties;
00106 
00107     int sortingKey;
00108 };
00109 }
00110 
00111 using namespace KoProperty;
00112 
00114 
00115 Property::ListData::ListData(const QStringList& keys_, const QStringList& names_)
00116  : names(names_)
00117 // , fixed(true)
00118 {
00119     setKeysAsStringList(keys_);
00120 }
00121 
00122 Property::ListData::ListData(const QValueList<QVariant> keys_, const QStringList& names_)
00123  : keys(keys_), names(names_)
00124 // , fixed(true)
00125 {
00126 }
00127 
00128 Property::ListData::ListData()
00129 // : fixed(true)
00130 {
00131 }
00132 
00133 Property::ListData::~ListData()
00134 {
00135 }
00136 
00137 void Property::ListData::setKeysAsStringList(const QStringList& list)
00138 {
00139     keys.clear();
00140     for (QStringList::ConstIterator it = list.constBegin(); it!=list.constEnd(); ++it) {
00141         keys.append(*it);
00142     }
00143 }
00144 
00145 QStringList Property::ListData::keysAsStringList() const
00146 {
00147     QStringList result;
00148     for (QValueList<QVariant>::ConstIterator it = keys.constBegin(); it!=keys.constEnd(); ++it) {
00149         result.append((*it).toString());
00150     }
00151     return result;
00152 }
00153 
00155 
00156 /*
00157 KOPROPERTY_EXPORT QMap<QString, QVariant>
00158 KoProperty::createValueListFromStringLists(const QStringList &keys, const QStringList &values)
00159 {
00160     QMap<QString, QVariant> map;
00161     if(keys.count() != values.count())
00162         return map;
00163 
00164     QStringList::ConstIterator valueIt = values.begin();
00165     QStringList::ConstIterator endIt = keys.constEnd();
00166     for(QStringList::ConstIterator it = keys.begin(); it != endIt; ++it, ++valueIt)
00167         map.insert( *it, *valueIt);
00168 
00169     return map;
00170 }
00171 */
00172 
00173 
00174 Property::Property(const QCString &name, const QVariant &value,
00175     const QString &caption, const QString &description,
00176     int type, Property* parent)
00177  : d( new PropertyPrivate() )
00178 {
00179     d->name = name;
00180     d->setCaptionForDisplaying(caption);
00181     d->description = description;
00182 
00183     if(type == Auto)
00184         d->type = value.type();
00185     else
00186         d->type = type;
00187 
00188     d->custom = FactoryManager::self()->createCustomProperty(this);
00189 
00190     if (parent)
00191         parent->addChild(this);
00192     setValue(value, false);
00193 }
00194 
00195 Property::Property(const QCString &name, const QStringList &keys, const QStringList &strings,
00196     const QVariant &value, const QString &caption, const QString &description, 
00197     int type, Property* parent)
00198  : d( new PropertyPrivate() )
00199 {
00200     d->name = name;
00201     d->setCaptionForDisplaying(caption);
00202     d->description = description;
00203     d->type = type;
00204     setListData(keys, strings);
00205 
00206     d->custom = FactoryManager::self()->createCustomProperty(this);
00207 
00208     if (parent)
00209         parent->addChild(this);
00210     setValue(value, false);
00211 }
00212 
00213 Property::Property(const QCString &name, ListData* listData, 
00214     const QVariant &value, const QString &caption, const QString &description, 
00215     int type, Property* parent)
00216  : d( new PropertyPrivate() )
00217 {
00218     d->name = name;
00219     d->setCaptionForDisplaying(caption);
00220     d->description = description;
00221     d->type = type;
00222     d->listData = listData;
00223 
00224     d->custom = FactoryManager::self()->createCustomProperty(this);
00225 
00226     if (parent)
00227         parent->addChild(this);
00228     setValue(value, false);
00229 }
00230 
00231 Property::Property()
00232  : d( new PropertyPrivate() )
00233 {
00234 }
00235 
00236 Property::Property(const Property &prop)
00237  : d( new PropertyPrivate() )
00238 {
00239     *this = prop;
00240 }
00241 
00242 Property::~Property()
00243 {
00244     delete d;
00245     d = 0;
00246 }
00247 
00248 QCString
00249 Property::name() const
00250 {
00251     return d->name;
00252 }
00253 
00254 void
00255 Property::setName(const QCString &name)
00256 {
00257     d->name = name;
00258 }
00259 
00260 QString
00261 Property::caption() const
00262 {
00263     return d->caption ? *d->caption : d->captionForDisplaying;
00264 }
00265 
00266 QString
00267 Property::captionForDisplaying() const
00268 {
00269     return d->captionForDisplaying;
00270 }
00271 
00272 void
00273 Property::setCaption(const QString &caption)
00274 {
00275     d->setCaptionForDisplaying(caption);
00276 }
00277 
00278 QString
00279 Property::description() const
00280 {
00281     return d->description;
00282 }
00283 
00284 void
00285 Property::setDescription(const QString &desc)
00286 {
00287     d->description = desc;
00288 }
00289 
00290 int
00291 Property::type() const
00292 {
00293     return d->type;
00294 }
00295 
00296 void
00297 Property::setType(int type)
00298 {
00299     d->type = type;
00300 }
00301 
00302 QString
00303 Property::icon() const
00304 {
00305     return d->icon;
00306 }
00307 
00308 void
00309 Property::setIcon(const QString &icon)
00310 {
00311     d->icon = icon;
00312 }
00313 
00314 QVariant
00315 Property::value() const
00316 {
00317     if(d->custom && d->custom->handleValue())
00318         return d->custom->value();
00319     return d->value;
00320 }
00321 
00322 QVariant
00323 Property::oldValue() const
00324 {
00325     if(d->oldValue.isNull())
00326         return value();
00327     else
00328         return d->oldValue;
00329 }
00330 
00331 void
00332 Property::setValue(const QVariant &value, bool rememberOldValue, bool useCustomProperty)
00333 {
00334     if (d->name.isEmpty()) {
00335         kopropertywarn << "Property::setValue(): COULD NOT SET value to a null property" << endl;
00336         return;
00337     }
00338     QVariant currentValue = this->value();
00339     const QVariant::Type t = currentValue.type();
00340     const QVariant::Type newt = value.type();
00341 //  kopropertydbg << d->name << " : setValue('" << value.toString() << "' type=" << type() << ")" << endl;
00342     if (t != newt && !currentValue.isNull() && !value.isNull()
00343          && !( (t==QVariant::Int && newt==QVariant::UInt)
00344                || (t==QVariant::UInt && newt==QVariant::Int)
00345                || (t==QVariant::CString && newt==QVariant::String)
00346                || (t==QVariant::String && newt==QVariant::CString)
00347          )) {
00348         kopropertywarn << "Property::setValue(): INCOMPAT TYPES! " << currentValue.typeName() 
00349             << " and " << value.typeName() << endl;
00350     }
00351 
00352     //1. Check if the value should be changed
00353     bool ch;
00354     if (t == QVariant::DateTime
00355         || t == QVariant::Time) {
00356         //for date and datetime types: compare with strings, because there
00357         //can be miliseconds difference
00358         ch = (currentValue.toString() != value.toString());
00359     }
00360     else if (t == QVariant::String || t==QVariant::CString) {
00361         //property is changed for string type,
00362         //if one of value is empty and other isn't..
00363         ch = ( (currentValue.toString().isEmpty() != value.toString().isEmpty())
00364         //..or both are not empty and values differ
00365             || (!currentValue.toString().isEmpty() && !value.toString().isEmpty() && currentValue != value) );
00366     }
00367     else
00368         ch = (currentValue != value);
00369 
00370     if (!ch)
00371         return;
00372 
00373     //2. Then change it, and store old value if necessary
00374     if(rememberOldValue) {
00375         if(!d->changed)
00376             d->oldValue = currentValue;
00377         d->changed = true;
00378     }
00379     else {
00380         d->oldValue = QVariant(); // clear old value
00381         d->changed = false;
00382     }
00383     QVariant prevValue;
00384     if(d->custom && useCustomProperty) {
00385         d->custom->setValue(value, rememberOldValue);
00386         prevValue = d->custom->value();
00387     }
00388     else
00389         prevValue = currentValue;
00390 
00391     if (!d->custom || !useCustomProperty || !d->custom->handleValue())
00392         d->value = value;
00393 
00394     if (d->sets) {
00395         for (QPtrDictIterator< QGuardedPtr<Set> > it(*d->sets); it.current(); ++it) {
00396             if (it.current()) {//may be destroyed in the meantime
00397                 emit (*it.current())->propertyChanged(**it.current(), *this, prevValue);
00398                 emit (*it.current())->propertyChanged(**it.current(), *this);
00399                 emit (*it.current())->propertyChanged();
00400             }
00401         }
00402     }
00403     else if (d->set) {
00404         emit d->set->propertyChanged(*d->set, *this, prevValue);
00405         emit d->set->propertyChanged(*d->set, *this);
00406         emit d->set->propertyChanged();
00407     }
00408 }
00409 
00410 void
00411 Property::resetValue()
00412 {
00413     d->changed = false;
00414     setValue(oldValue(), false);
00415     // maybe parent  prop is also unchanged now
00416     if(d->parent && d->parent->value() == d->parent->oldValue())
00417         d->parent->d->changed = false;
00418 
00419     if (d->sets) {
00420         for (QPtrDictIterator< QGuardedPtr<Set> > it(*d->sets); it.current(); ++it) {
00421             if (it.current()) //may be destroyed in the meantime
00422                 emit (*it.current())->propertyReset(**it.current(), *this);
00423         }
00424     }
00425     else if (d->set) {
00426         emit d->set->propertyReset(*d->set, *this);
00427     }
00428 }
00429 
00430 //const QMap<QString, QVariant>*
00431 Property::ListData*
00432 Property::listData() const
00433 {
00434     return d->listData;
00435 }
00436 
00437 void
00438 Property::setListData(ListData* list) //const QMap<QString, QVariant> &list)
00439 {
00440 //  if(!d->valueList)
00441 //      d->valueList = new QMap<QString, QVariant>();
00442     if (list == d->listData)
00443         return;
00444     delete d->listData;
00445     d->listData = list;
00446 }
00447 
00448 void
00449 Property::setListData(const QStringList &keys, const QStringList &names)
00450 {
00451     ListData* list = new ListData(keys, names);
00452     setListData(list);
00453 
00454 //  if(!d->valueList)
00455 //      d->valueList = new QMap<QString, QVariant>();
00456 //  *(d->valueList) = createValueListFromStringLists(keys, values);
00457 }
00458 
00460 
00461 bool
00462 Property::isNull() const
00463 {
00464     return d->name.isEmpty();
00465 }
00466 
00467 bool
00468 Property::isModified() const
00469 {
00470     return d->changed;
00471 }
00472 
00473 bool
00474 Property::isReadOnly() const
00475 {
00476     return d->readOnly;
00477 }
00478 
00479 void
00480 Property::setReadOnly(bool readOnly)
00481 {
00482     d->readOnly = readOnly;
00483 }
00484 
00485 bool
00486 Property::isVisible() const
00487 {
00488     return d->visible;
00489 }
00490 
00491 void
00492 Property::setVisible(bool visible)
00493 {
00494     d->visible = visible;
00495 }
00496 
00497 int
00498 Property::autoSync() const
00499 {
00500     return d->autosync;
00501 }
00502 
00503 void
00504 Property::setAutoSync(int sync)
00505 {
00506     d->autosync = sync;
00507 }
00508 
00509 bool
00510 Property::isStorable() const
00511 {
00512     return d->storable;
00513 }
00514 
00515 void
00516 Property::setStorable(bool storable)
00517 {
00518     d->storable = storable;
00519 }
00520 
00521 void
00522 Property::setOption(const char* name, const QVariant& val)
00523 {
00524     d->options[name] = val;
00525 }
00526 
00527 QVariant
00528 Property::option(const char* name) const
00529 {
00530     if (d->options.contains(name))
00531         return d->options[name];
00532     return QVariant();
00533 }
00534 
00535 bool
00536 Property::hasOptions() const
00537 {
00538     return !d->options.isEmpty();
00539 }
00540 
00542 
00543 Property::operator bool () const
00544 {
00545     return !isNull();
00546 }
00547 
00548 const Property&
00549 Property::operator= (const QVariant& val)
00550 {
00551     setValue(val);
00552     return *this;
00553 }
00554 
00555 const Property&
00556 Property::operator= (const Property &property)
00557 {
00558     if(&property == this)
00559         return *this;
00560 
00561     if(d->listData) {
00562         delete d->listData;
00563         d->listData = 0;
00564     }
00565     if(d->children) {
00566         delete d->children;
00567         d->children = 0;
00568     }
00569     if(d->relatedProperties) {
00570         delete d->relatedProperties;
00571         d->relatedProperties = 0;
00572     }
00573     if(d->custom) {
00574         delete d->custom;
00575         d->custom = 0;
00576     }
00577 
00578     d->name = property.d->name;
00579     d->setCaptionForDisplaying(property.captionForDisplaying());
00580     d->description = property.d->description;
00581     d->type = property.d->type;
00582     d->value = property.d->value;
00583 
00584     d->icon = property.d->icon;
00585     d->autosync = property.d->autosync;
00586     d->visible = property.d->visible;
00587     d->storable = property.d->storable;
00588     d->readOnly = property.d->readOnly;
00589     d->options = property.d->options;
00590 
00591     if(property.d->listData) {
00592         d->listData = new ListData(*property.d->listData); //QMap<QString, QVariant>(*(property.d->valueList));
00593     }
00594     if(property.d->children) {
00595         if(property.d->custom) {
00596             d->custom = FactoryManager::self()->createCustomProperty(this);
00597             // updates all children value, using CustomProperty
00598             setValue(property.d->value);
00599         }
00600         else {
00601             // no CustomProperty (should never happen), simply copy all children
00602             QValueList<Property*>::ConstIterator endIt = d->children->constEnd();
00603             for(QValueList<Property*>::ConstIterator it = d->children->constBegin(); it != endIt; ++it) {
00604                 Property *child = new Property( *(*it) );
00605                 addChild(child);
00606             }
00607         }
00608     }
00609 
00610     if(property.d->relatedProperties) {
00611         d->relatedProperties = new QValueList<Property*>( *(property.d->relatedProperties));
00612     }
00613 
00614     // update these later because they may have been changed when creating children
00615     d->oldValue = property.d->oldValue;
00616     d->changed = property.d->changed;
00617 
00618     return *this;
00619 }
00620 
00621 bool
00622 Property::operator ==(const Property &prop) const
00623 {
00624     return ((d->name == prop.d->name) && (value() == prop.value()));
00625 }
00626 
00628 
00629 const QValueList<Property*>*
00630 Property::children() const
00631 {
00632     return d->children;
00633 }
00634 
00635 Property*
00636 Property::child(const QCString &name)
00637 {
00638     QValueList<Property*>::ConstIterator endIt = d->children->constEnd();
00639     for(QValueList<Property*>::ConstIterator it = d->children->constBegin(); it != endIt; ++it) {
00640         if((*it)->name() == name)
00641             return *it;
00642     }
00643     return 0;
00644 }
00645 
00646 Property*
00647 Property::parent() const
00648 {
00649     return d->parent;
00650 }
00651 
00652 void
00653 Property::addChild(Property *prop)
00654 {
00655     if (!prop)
00656         return;
00657 
00658     if(!d->children || qFind( d->children->begin(), d->children->end(), prop) == d->children->end()) { // not in our list
00659         if(!d->children)
00660             d->children = new QValueList<Property*>();
00661         d->children->append(prop);
00662         prop->setSortingKey(d->children->count());
00663         prop->d->parent = this;
00664     }
00665     else {
00666         kopropertywarn << "Property::addChild(): property \"" << name() 
00667             << "\": child property \"" << prop->name() << "\" already added" << endl;
00668         return;
00669     }
00670 }
00671 
00672 void
00673 Property::addSet(Set *set)
00674 {
00675     if (!set)
00676         return;
00677 
00678     if (!d->set) {//simple case
00679         d->set = set;
00680         return;
00681     }
00682     if ((Set*)d->set==set)
00683         return;
00684     QGuardedPtr<Set> *pset = d->sets ? d->sets->find(set) : 0;
00685     if (pset && (Set*)*pset == set)
00686         return;
00687     if (!d->sets) {
00688         d->sets = new QPtrDict< QGuardedPtr<Set> >( 101 );
00689         d->sets->setAutoDelete(true);
00690     }
00691 
00692     d->sets->replace(set, new QGuardedPtr<Set>( set ));
00693 
00694 //  QValueList<Set*>::iterator it = qFind( d->sets.begin(), d->sets.end(), set);
00695 //  if(it == d->sets.end()) // not in our list
00696 //      d->sets.append(set);
00697 }
00698 
00699 const QValueList<Property*>*
00700 Property::related() const
00701 {
00702     return d->relatedProperties;
00703 }
00704 
00705 void
00706 Property::addRelatedProperty(Property *property)
00707 {
00708     if(!d->relatedProperties)
00709         d->relatedProperties = new QValueList<Property*>();
00710 
00711     QValueList<Property*>::iterator it = qFind( d->relatedProperties->begin(), d->relatedProperties->end(), property);
00712     if(it == d->relatedProperties->end()) // not in our list
00713         d->relatedProperties->append(property);
00714 }
00715 
00716 void
00717 Property::setCustomProperty(CustomProperty *prop)
00718 {
00719     d->custom = prop;
00720 }
00721 
00722 int Property::sortingKey() const
00723 {
00724     return d->sortingKey;
00725 }
00726 
00727 void Property::setSortingKey(int key)
00728 {
00729     d->sortingKey = key;
00730 }
00731 
00733 
00734 void
00735 Property::debug()
00736 {
00737     QString dbg = "Property( name='" + QString(d->name) + "' desc='" + d->description
00738         + "' val=" + (value().isValid() ? value().toString() : "<INVALID>");
00739     if (!d->oldValue.isValid())
00740         dbg += (", oldVal='" + d->oldValue.toString() + "'");
00741     dbg += (QString(d->changed ? " " : " un") + "changed");
00742     dbg += (d->visible ? " visible" : " hidden");
00743     dbg+=" )";
00744 
00745     kopropertydbg << dbg << endl;
00746 }
KDE Home | KDE Accessibility Home | Description of Access Keys