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