00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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 listData;
00068 delete children;
00069 delete relatedProperties;
00070 delete custom;
00071 delete sets;
00072 }
00073
00074 int type;
00075 QCString name;
00076 QString captionForDisplaying;
00077 QString* caption;
00078 QString description;
00079 QVariant value;
00080 QVariant oldValue;
00082 Property::ListData* listData;
00083
00084 QString icon;
00085
00086 bool changed : 1;
00087 bool storable : 1;
00088 bool readOnly : 1;
00089 bool visible : 1;
00090 int autosync;
00091 QMap<QCString, QVariant> options;
00092
00093 CustomProperty *custom;
00095 bool useCustomProperty;
00096
00098 QGuardedPtr<Set> set;
00100 QPtrDict< QGuardedPtr<Set> > *sets;
00101
00102
00103 Property *parent;
00104 QValueList<Property*> *children;
00106 QValueList<Property*> *relatedProperties;
00107
00108 int sortingKey;
00109 };
00110 }
00111
00112 using namespace KoProperty;
00113
00115
00116 Property::ListData::ListData(const QStringList& keys_, const QStringList& names_)
00117 : names(names_)
00118
00119 {
00120 setKeysAsStringList(keys_);
00121 }
00122
00123 Property::ListData::ListData(const QValueList<QVariant> keys_, const QStringList& names_)
00124 : keys(keys_), names(names_)
00125
00126 {
00127 }
00128
00129 Property::ListData::ListData()
00130
00131 {
00132 }
00133
00134 Property::ListData::~ListData()
00135 {
00136 }
00137
00138 void Property::ListData::setKeysAsStringList(const QStringList& list)
00139 {
00140 keys.clear();
00141 for (QStringList::ConstIterator it = list.constBegin(); it!=list.constEnd(); ++it) {
00142 keys.append(*it);
00143 }
00144 }
00145
00146 QStringList Property::ListData::keysAsStringList() const
00147 {
00148 QStringList result;
00149 for (QValueList<QVariant>::ConstIterator it = keys.constBegin(); it!=keys.constEnd(); ++it) {
00150 result.append((*it).toString());
00151 }
00152 return result;
00153 }
00154
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175 Property::Property(const QCString &name, const QVariant &value,
00176 const QString &caption, const QString &description,
00177 int type, Property* parent)
00178 : d( new PropertyPrivate() )
00179 {
00180 d->name = name;
00181 d->setCaptionForDisplaying(caption);
00182 d->description = description;
00183
00184 if(type == Auto)
00185 d->type = value.type();
00186 else
00187 d->type = type;
00188
00189 d->custom = FactoryManager::self()->createCustomProperty(this);
00190
00191 if (parent)
00192 parent->addChild(this);
00193 setValue(value, false);
00194 }
00195
00196 Property::Property(const QCString &name, const QStringList &keys, const QStringList &strings,
00197 const QVariant &value, const QString &caption, const QString &description,
00198 int type, Property* parent)
00199 : d( new PropertyPrivate() )
00200 {
00201 d->name = name;
00202 d->setCaptionForDisplaying(caption);
00203 d->description = description;
00204 d->type = type;
00205 setListData(keys, strings);
00206
00207 d->custom = FactoryManager::self()->createCustomProperty(this);
00208
00209 if (parent)
00210 parent->addChild(this);
00211 setValue(value, false);
00212 }
00213
00214 Property::Property(const QCString &name, ListData* listData,
00215 const QVariant &value, const QString &caption, const QString &description,
00216 int type, Property* parent)
00217 : d( new PropertyPrivate() )
00218 {
00219 d->name = name;
00220 d->setCaptionForDisplaying(caption);
00221 d->description = description;
00222 d->type = type;
00223 d->listData = listData;
00224
00225 d->custom = FactoryManager::self()->createCustomProperty(this);
00226
00227 if (parent)
00228 parent->addChild(this);
00229 setValue(value, false);
00230 }
00231
00232 Property::Property()
00233 : d( new PropertyPrivate() )
00234 {
00235 }
00236
00237 Property::Property(const Property &prop)
00238 : d( new PropertyPrivate() )
00239 {
00240 *this = prop;
00241 }
00242
00243 Property::~Property()
00244 {
00245 delete d;
00246 d = 0;
00247 }
00248
00249 QCString
00250 Property::name() const
00251 {
00252 return d->name;
00253 }
00254
00255 void
00256 Property::setName(const QCString &name)
00257 {
00258 d->name = name;
00259 }
00260
00261 QString
00262 Property::caption() const
00263 {
00264 return d->caption ? *d->caption : d->captionForDisplaying;
00265 }
00266
00267 QString
00268 Property::captionForDisplaying() const
00269 {
00270 return d->captionForDisplaying;
00271 }
00272
00273 void
00274 Property::setCaption(const QString &caption)
00275 {
00276 d->setCaptionForDisplaying(caption);
00277 }
00278
00279 QString
00280 Property::description() const
00281 {
00282 return d->description;
00283 }
00284
00285 void
00286 Property::setDescription(const QString &desc)
00287 {
00288 d->description = desc;
00289 }
00290
00291 int
00292 Property::type() const
00293 {
00294 return d->type;
00295 }
00296
00297 void
00298 Property::setType(int type)
00299 {
00300 d->type = type;
00301 }
00302
00303 QString
00304 Property::icon() const
00305 {
00306 return d->icon;
00307 }
00308
00309 void
00310 Property::setIcon(const QString &icon)
00311 {
00312 d->icon = icon;
00313 }
00314
00315 QVariant
00316 Property::value() const
00317 {
00318 if(d->custom && d->custom->handleValue())
00319 return d->custom->value();
00320 return d->value;
00321 }
00322
00323 QVariant
00324 Property::oldValue() const
00325 {
00326 if(d->oldValue.isNull())
00327 return value();
00328 else
00329 return d->oldValue;
00330 }
00331
00332 void
00333 Property::setValue(const QVariant &value, bool rememberOldValue, bool useCustomProperty)
00334 {
00335 if (d->name.isEmpty()) {
00336 kopropertywarn << "Property::setValue(): COULD NOT SET value to a null property" << endl;
00337 return;
00338 }
00339 QVariant currentValue = this->value();
00340 const QVariant::Type t = currentValue.type();
00341 const QVariant::Type newt = value.type();
00342
00343 if (t != newt && !currentValue.isNull() && !value.isNull()
00344 && !( (t==QVariant::Int && newt==QVariant::UInt)
00345 || (t==QVariant::UInt && newt==QVariant::Int)
00346 || (t==QVariant::CString && newt==QVariant::String)
00347 || (t==QVariant::String && newt==QVariant::CString)
00348 )) {
00349 kopropertywarn << "Property::setValue(): INCOMPAT TYPES! " << currentValue.typeName()
00350 << " and " << value.typeName() << endl;
00351 }
00352
00353
00354 bool ch;
00355 if (t == QVariant::DateTime
00356 || t == QVariant::Time) {
00357
00358
00359 ch = (currentValue.toString() != value.toString());
00360 }
00361 else if (t == QVariant::String || t==QVariant::CString) {
00362
00363
00364 ch = ( (currentValue.toString().isEmpty() != value.toString().isEmpty())
00365
00366 || (!currentValue.toString().isEmpty() && !value.toString().isEmpty() && currentValue != value) );
00367 }
00368 else
00369 ch = (currentValue != value);
00370
00371 if (!ch)
00372 return;
00373
00374
00375 if(rememberOldValue) {
00376 if(!d->changed)
00377 d->oldValue = currentValue;
00378 d->changed = true;
00379 }
00380 else {
00381 d->oldValue = QVariant();
00382 d->changed = false;
00383 }
00384 QVariant prevValue;
00385 if(d->custom && useCustomProperty) {
00386 d->custom->setValue(value, rememberOldValue);
00387 prevValue = d->custom->value();
00388 }
00389 else
00390 prevValue = currentValue;
00391
00392 if (!d->custom || !useCustomProperty || !d->custom->handleValue())
00393 d->value = value;
00394
00395 if (d->sets) {
00396 for (QPtrDictIterator< QGuardedPtr<Set> > it(*d->sets); it.current(); ++it) {
00397 if (it.current()) {
00398 emit (*it.current())->propertyChanged(**it.current(), *this);
00399 }
00400 }
00401 }
00402 else if (d->set) {
00403
00404
00405
00406
00407
00408
00409 emit d->set->propertyChanged(*d->set, *this);
00410 }
00411 }
00412
00413 void
00414 Property::resetValue()
00415 {
00416 d->changed = false;
00417 setValue(oldValue(), false);
00418
00419 if(d->parent && d->parent->value() == d->parent->oldValue())
00420 d->parent->d->changed = false;
00421
00422 if (d->sets) {
00423 for (QPtrDictIterator< QGuardedPtr<Set> > it(*d->sets); it.current(); ++it) {
00424 if (it.current())
00425 emit (*it.current())->propertyReset(**it.current(), *this);
00426 }
00427 }
00428 else if (d->set) {
00429 emit d->set->propertyReset(*d->set, *this);
00430 }
00431 }
00432
00433
00434 Property::ListData*
00435 Property::listData() const
00436 {
00437 return d->listData;
00438 }
00439
00440 void
00441 Property::setListData(ListData* list)
00442 {
00443
00444
00445 if (list == d->listData)
00446 return;
00447 delete d->listData;
00448 d->listData = list;
00449 }
00450
00451 void
00452 Property::setListData(const QStringList &keys, const QStringList &names)
00453 {
00454 ListData* list = new ListData(keys, names);
00455 setListData(list);
00456
00457
00458
00459
00460 }
00461
00463
00464 bool
00465 Property::isNull() const
00466 {
00467 return d->name.isEmpty();
00468 }
00469
00470 bool
00471 Property::isModified() const
00472 {
00473 return d->changed;
00474 }
00475
00476 bool
00477 Property::isReadOnly() const
00478 {
00479 return d->readOnly;
00480 }
00481
00482 void
00483 Property::setReadOnly(bool readOnly)
00484 {
00485 d->readOnly = readOnly;
00486 }
00487
00488 bool
00489 Property::isVisible() const
00490 {
00491 return d->visible;
00492 }
00493
00494 void
00495 Property::setVisible(bool visible)
00496 {
00497 d->visible = visible;
00498 }
00499
00500 int
00501 Property::autoSync() const
00502 {
00503 return d->autosync;
00504 }
00505
00506 void
00507 Property::setAutoSync(int sync)
00508 {
00509 d->autosync = sync;
00510 }
00511
00512 bool
00513 Property::isStorable() const
00514 {
00515 return d->storable;
00516 }
00517
00518 void
00519 Property::setStorable(bool storable)
00520 {
00521 d->storable = storable;
00522 }
00523
00524 void
00525 Property::setOption(const char* name, const QVariant& val)
00526 {
00527 d->options[name] = val;
00528 }
00529
00530 QVariant
00531 Property::option(const char* name) const
00532 {
00533 if (d->options.contains(name))
00534 return d->options[name];
00535 return QVariant();
00536 }
00537
00538 bool
00539 Property::hasOptions() const
00540 {
00541 return !d->options.isEmpty();
00542 }
00543
00545
00546 Property::operator bool () const
00547 {
00548 return !isNull();
00549 }
00550
00551 const Property&
00552 Property::operator= (const QVariant& val)
00553 {
00554 setValue(val);
00555 return *this;
00556 }
00557
00558 const Property&
00559 Property::operator= (const Property &property)
00560 {
00561 if(&property == this)
00562 return *this;
00563
00564 if(d->listData) {
00565 delete d->listData;
00566 d->listData = 0;
00567 }
00568 if(d->children) {
00569 delete d->children;
00570 d->children = 0;
00571 }
00572 if(d->relatedProperties) {
00573 delete d->relatedProperties;
00574 d->relatedProperties = 0;
00575 }
00576 if(d->custom) {
00577 delete d->custom;
00578 d->custom = 0;
00579 }
00580
00581 d->name = property.d->name;
00582 d->setCaptionForDisplaying(property.captionForDisplaying());
00583 d->description = property.d->description;
00584 d->type = property.d->type;
00585
00586 d->icon = property.d->icon;
00587 d->autosync = property.d->autosync;
00588 d->visible = property.d->visible;
00589 d->storable = property.d->storable;
00590 d->readOnly = property.d->readOnly;
00591 d->options = property.d->options;
00592
00593 if(property.d->listData) {
00594 d->listData = new ListData(*property.d->listData);
00595 }
00596 if(property.d->custom) {
00597 d->custom = FactoryManager::self()->createCustomProperty(this);
00598
00599 setValue(property.value());
00600 }
00601 else {
00602 d->value = property.d->value;
00603 if(property.d->children) {
00604
00605 d->children = new QValueList<Property*>();
00606 QValueList<Property*>::ConstIterator endIt = property.d->children->constEnd();
00607 for(QValueList<Property*>::ConstIterator it = property.d->children->constBegin(); it != endIt; ++it) {
00608 Property *child = new Property( *(*it) );
00609 addChild(child);
00610 }
00611 }
00612 }
00613
00614 if(property.d->relatedProperties) {
00615 d->relatedProperties = new QValueList<Property*>( *(property.d->relatedProperties));
00616 }
00617
00618
00619 d->oldValue = property.d->oldValue;
00620 d->changed = property.d->changed;
00621 d->sortingKey = property.d->sortingKey;
00622
00623 return *this;
00624 }
00625
00626 bool
00627 Property::operator ==(const Property &prop) const
00628 {
00629 return ((d->name == prop.d->name) && (value() == prop.value()));
00630 }
00631
00633
00634 const QValueList<Property*>*
00635 Property::children() const
00636 {
00637 return d->children;
00638 }
00639
00640 Property*
00641 Property::child(const QCString &name)
00642 {
00643 QValueList<Property*>::ConstIterator endIt = d->children->constEnd();
00644 for(QValueList<Property*>::ConstIterator it = d->children->constBegin(); it != endIt; ++it) {
00645 if((*it)->name() == name)
00646 return *it;
00647 }
00648 return 0;
00649 }
00650
00651 Property*
00652 Property::parent() const
00653 {
00654 return d->parent;
00655 }
00656
00657 void
00658 Property::addChild(Property *prop)
00659 {
00660 if (!prop)
00661 return;
00662
00663 if(!d->children || qFind( d->children->begin(), d->children->end(), prop) == d->children->end()) {
00664 if(!d->children)
00665 d->children = new QValueList<Property*>();
00666 d->children->append(prop);
00667 prop->setSortingKey(d->children->count());
00668 prop->d->parent = this;
00669 }
00670 else {
00671 kopropertywarn << "Property::addChild(): property \"" << name()
00672 << "\": child property \"" << prop->name() << "\" already added" << endl;
00673 return;
00674 }
00675 }
00676
00677 void
00678 Property::addSet(Set *set)
00679 {
00680 if (!set)
00681 return;
00682
00683 if (!d->set) {
00684 d->set = set;
00685 return;
00686 }
00687 if ((Set*)d->set==set)
00688 return;
00689 QGuardedPtr<Set> *pset = d->sets ? d->sets->find(set) : 0;
00690 if (pset && (Set*)*pset == set)
00691 return;
00692 if (!d->sets) {
00693 d->sets = new QPtrDict< QGuardedPtr<Set> >( 101 );
00694 d->sets->setAutoDelete(true);
00695 }
00696
00697 d->sets->replace(set, new QGuardedPtr<Set>( set ));
00698
00699
00700
00701
00702 }
00703
00704 const QValueList<Property*>*
00705 Property::related() const
00706 {
00707 return d->relatedProperties;
00708 }
00709
00710 void
00711 Property::addRelatedProperty(Property *property)
00712 {
00713 if(!d->relatedProperties)
00714 d->relatedProperties = new QValueList<Property*>();
00715
00716 QValueList<Property*>::iterator it = qFind( d->relatedProperties->begin(), d->relatedProperties->end(), property);
00717 if(it == d->relatedProperties->end())
00718 d->relatedProperties->append(property);
00719 }
00720
00721 void
00722 Property::setCustomProperty(CustomProperty *prop)
00723 {
00724 d->custom = prop;
00725 }
00726
00727 int Property::sortingKey() const
00728 {
00729 return d->sortingKey;
00730 }
00731
00732 void Property::setSortingKey(int key)
00733 {
00734 d->sortingKey = key;
00735 }
00736
00738
00739 void
00740 Property::debug()
00741 {
00742 QString dbg = "Property( name='" + QString(d->name) + "' desc='" + d->description
00743 + "' val=" + (value().isValid() ? value().toString() : "<INVALID>");
00744 if (!d->oldValue.isValid())
00745 dbg += (", oldVal='" + d->oldValue.toString() + "'");
00746 dbg += (QString(d->changed ? " " : " un") + "changed");
00747 dbg += (d->visible ? " visible" : " hidden");
00748 dbg+=" )";
00749
00750 kopropertydbg << dbg << endl;
00751 }