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>
00030 #include <q3ptrdict.h>
00031 #include <q3asciidict.h>
00032 #include <QPointer>
00033 #include <QByteArray>
00034 #include <QStringList>
00035 namespace KoProperty {
00036
00037 QT_STATIC_CONST_IMPL Property Property::null;
00038
00040 class PropertyPrivate
00041 {
00042 public:
00043 PropertyPrivate()
00044 : caption(0), listData(0), changed(false), storable(true),
00045 readOnly(false), visible(true),
00046 autosync(-1), custom(0), useCustomProperty(true),
00047 sets(0), parent(0), children(0), relatedProperties(0),
00048 sortingKey(0)
00049 {
00050 }
00051
00052 inline void setCaptionForDisplaying(const QString& captionForDisplaying)
00053 {
00054 delete caption;
00055 if (captionForDisplaying.simplified()!=captionForDisplaying)
00056 caption = new QString(captionForDisplaying.simplified());
00057 else
00058 caption = 0;
00059 this->captionForDisplaying = captionForDisplaying;
00060 }
00061
00062 ~PropertyPrivate()
00063 {
00064 delete caption;
00065 caption = 0;
00066 delete listData;
00067 delete children;
00068 delete relatedProperties;
00069 delete custom;
00070 delete sets;
00071 }
00072
00073 int type;
00074 QByteArray 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<QByteArray, QVariant> options;
00091
00092 CustomProperty *custom;
00094 bool useCustomProperty;
00095
00097 QPointer<Set> set;
00099 Q3PtrDict< QPointer<Set> > *sets;
00100
00101
00102 Property *parent;
00103 QList<Property*> *children;
00105 QList<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 QList<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 (QList<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 QByteArray &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 == (int)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 QByteArray &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 QByteArray &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 QByteArray
00249 Property::name() const
00250 {
00251 return d->name;
00252 }
00253
00254 void
00255 Property::setName(const QByteArray &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
00326
00327
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 || (t==QVariant::ULongLong && newt==QVariant::LongLong)
00348 || (t==QVariant::LongLong && newt==QVariant::ULongLong)
00349 )) {
00350 kopropertywarn << "Property::setValue(): INCOMPATIBLE TYPES! old=" << currentValue
00351 << " new=" << value << endl;
00352 }
00353
00354
00355 bool ch;
00356 if (t == QVariant::DateTime
00357 || t == QVariant::Time) {
00358
00359
00360 ch = (currentValue.toString() != value.toString());
00361 }
00362 else if (t == QVariant::String || t==QVariant::CString) {
00363
00364
00365 ch = ( (currentValue.toString().isEmpty() != value.toString().isEmpty())
00366
00367 || (!currentValue.toString().isEmpty() && !value.toString().isEmpty() && currentValue != value) );
00368 }
00369 else if (t == QVariant::Invalid && newt == QVariant::Invalid)
00370 ch = false;
00371 else
00372 ch = (currentValue != value);
00373
00374 if (!ch)
00375 return;
00376
00377
00378 if(rememberOldValue) {
00379 if(!d->changed)
00380 d->oldValue = currentValue;
00381 d->changed = true;
00382 }
00383 else {
00384 d->oldValue = QVariant();
00385 d->changed = false;
00386 }
00387 QVariant prevValue;
00388 if(d->custom && useCustomProperty) {
00389 d->custom->setValue(value, rememberOldValue);
00390 prevValue = d->custom->value();
00391 }
00392 else
00393 prevValue = currentValue;
00394
00395 if (!d->custom || !useCustomProperty || !d->custom->handleValue())
00396 d->value = value;
00397
00398 emitPropertyChanged();
00399 }
00400
00401 void
00402 Property::resetValue()
00403 {
00404 d->changed = false;
00405 bool cleared = false;
00406 if (d->set)
00407 d->set->informAboutClearing(cleared);
00408 setValue(oldValue(), false);
00409 if (cleared)
00410 return;
00411
00412
00413 if(d->parent && d->parent->value() == d->parent->oldValue())
00414 d->parent->d->changed = false;
00415
00416 if (d->sets) {
00417 for (Q3PtrDictIterator< QPointer<Set> > it(*d->sets); it.current(); ++it) {
00418 if (it.current())
00419 emit (*it.current())->propertyReset(**it.current(), *this);
00420 }
00421 }
00422 else if (d->set) {
00423 emit d->set->propertyReset(*d->set, *this);
00424 }
00425 }
00426
00427
00428 Property::ListData*
00429 Property::listData() const
00430 {
00431 return d->listData;
00432 }
00433
00434 void
00435 Property::setListData(ListData* list)
00436 {
00437
00438
00439 if (list == d->listData)
00440 return;
00441 delete d->listData;
00442 d->listData = list;
00443 }
00444
00445 void
00446 Property::setListData(const QStringList &keys, const QStringList &names)
00447 {
00448 ListData* list = new ListData(keys, names);
00449 setListData(list);
00450
00451
00452
00453
00454 }
00455
00457
00458 bool
00459 Property::isNull() const
00460 {
00461 return d->name.isEmpty();
00462 }
00463
00464 bool
00465 Property::isModified() const
00466 {
00467 return d->changed;
00468 }
00469
00470 void
00471 Property::clearModifiedFlag()
00472 {
00473 d->changed = false;
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 QList<Property*>();
00606 QList<Property*>::ConstIterator endIt = property.d->children->constEnd();
00607 for(QList<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 QList<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 QList<Property*>*
00635 Property::children() const
00636 {
00637 return d->children;
00638 }
00639
00640 Property*
00641 Property::child(const QByteArray &name)
00642 {
00643 QList<Property*>::ConstIterator endIt = d->children->constEnd();
00644 for(QList<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 QList<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 QPointer<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 Q3PtrDict< QPointer<Set> >( 101 );
00694 d->sets->setAutoDelete(true);
00695 }
00696
00697 d->sets->replace(set, new QPointer<Set>( set ));
00698
00699
00700
00701
00702 }
00703
00704 const QList<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 QList<Property*>();
00715
00716 QList<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 CustomProperty*
00722 Property::customProperty() const
00723 {
00724 return d->custom;
00725 }
00726
00727 void
00728 Property::setCustomProperty(CustomProperty *prop)
00729 {
00730 d->custom = prop;
00731 }
00732
00733 int Property::sortingKey() const
00734 {
00735 return d->sortingKey;
00736 }
00737
00738 void Property::setSortingKey(int key)
00739 {
00740 d->sortingKey = key;
00741 }
00742
00743 void Property::emitPropertyChanged()
00744 {
00745 if (d->sets) {
00746 for (Q3PtrDictIterator< QPointer<Set> > it(*d->sets); it.current(); ++it) {
00747 if (it.current()) {
00748 emit (*it.current())->propertyChangedInternal(**it.current(), *this);
00749 emit (*it.current())->propertyChanged(**it.current(), *this);
00750 }
00751 }
00752 }
00753 else if (d->set) {
00754
00755
00756
00757
00758
00759
00760
00761 emit d->set->propertyChanged(*d->set, *this);
00762 }
00763 }
00764
00766
00767 void
00768 Property::debug()
00769 {
00770 QString dbg = "Property( name='" + QString(d->name) + "' desc='" + d->description
00771 + "' val=" + (value().isValid() ? value().toString() : "<INVALID>");
00772 if (!d->oldValue.isValid())
00773 dbg += (", oldVal='" + d->oldValue.toString() + '\'');
00774 dbg += (QString(d->changed ? " " : " un") + "changed");
00775 dbg += (d->visible ? " visible" : " hidden");
00776 dbg+=" )";
00777
00778 kopropertydbg << dbg << endl;
00779 }