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 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
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
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
00118 {
00119 setKeysAsStringList(keys_);
00120 }
00121
00122 Property::ListData::ListData(const QValueList<QVariant> keys_, const QStringList& names_)
00123 : keys(keys_), names(names_)
00124
00125 {
00126 }
00127
00128 Property::ListData::ListData()
00129
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
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
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
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
00353 bool ch;
00354 if (t == QVariant::DateTime
00355 || t == QVariant::Time) {
00356
00357
00358 ch = (currentValue.toString() != value.toString());
00359 }
00360 else if (t == QVariant::String || t==QVariant::CString) {
00361
00362
00363 ch = ( (currentValue.toString().isEmpty() != value.toString().isEmpty())
00364
00365 || (!currentValue.toString().isEmpty() && !value.toString().isEmpty() && currentValue != value) );
00366 }
00367 else
00368 ch = (currentValue != value);
00369
00370 if (!ch)
00371 return;
00372
00373
00374 if(rememberOldValue) {
00375 if(!d->changed)
00376 d->oldValue = currentValue;
00377 d->changed = true;
00378 }
00379 else {
00380 d->oldValue = QVariant();
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()) {
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
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())
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
00431 Property::ListData*
00432 Property::listData() const
00433 {
00434 return d->listData;
00435 }
00436
00437 void
00438 Property::setListData(ListData* list)
00439 {
00440
00441
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
00455
00456
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);
00593 }
00594 if(property.d->children) {
00595 if(property.d->custom) {
00596 d->custom = FactoryManager::self()->createCustomProperty(this);
00597
00598 setValue(property.d->value);
00599 }
00600 else {
00601
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
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()) {
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) {
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
00695
00696
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())
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 }