diff options
author | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-01-20 01:29:50 +0000 |
---|---|---|
committer | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-01-20 01:29:50 +0000 |
commit | 8362bf63dea22bbf6736609b0f49c152f975eb63 (patch) | |
tree | 0eea3928e39e50fae91d4e68b21b1e6cbae25604 /lib/koproperty/property.cpp | |
download | koffice-8362bf63dea22bbf6736609b0f49c152f975eb63.tar.gz koffice-8362bf63dea22bbf6736609b0f49c152f975eb63.zip |
Added old abandoned KDE3 version of koffice
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/koffice@1077364 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'lib/koproperty/property.cpp')
-rw-r--r-- | lib/koproperty/property.cpp | 778 |
1 files changed, 778 insertions, 0 deletions
diff --git a/lib/koproperty/property.cpp b/lib/koproperty/property.cpp new file mode 100644 index 00000000..9d677bd8 --- /dev/null +++ b/lib/koproperty/property.cpp @@ -0,0 +1,778 @@ +/* This file is part of the KDE project + Copyright (C) 2004 Cedric Pasteur <[email protected]> + Copyright (C) 2004 Alexander Dymo <[email protected]> + Copyright (C) 2004-2006 Jaroslaw Staniek <[email protected]> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include "property.h" +#include "customproperty.h" +#include "set.h" +#include "factory.h" + +#include <kdebug.h> + +#include <qobject.h> +#include <qptrdict.h> +#include <qasciidict.h> +#include <qguardedptr.h> + +namespace KoProperty { + +QT_STATIC_CONST_IMPL Property Property::null; + +//! @internal +class PropertyPrivate +{ + public: + PropertyPrivate() + : caption(0), listData(0), changed(false), storable(true), + readOnly(false), visible(true), + autosync(-1), custom(0), useCustomProperty(true), + sets(0), parent(0), children(0), relatedProperties(0), + sortingKey(0) + { + } + + inline void setCaptionForDisplaying(const QString& captionForDisplaying) + { + delete caption; + if (captionForDisplaying.simplifyWhiteSpace()!=captionForDisplaying) + caption = new QString(captionForDisplaying.simplifyWhiteSpace()); + else + caption = 0; + this->captionForDisplaying = captionForDisplaying; + } + + ~PropertyPrivate() + { + delete caption; + caption = 0; + delete listData; + delete children; + delete relatedProperties; + delete custom; + delete sets; + } + + int type; + QCString name; + QString captionForDisplaying; + QString* caption; + QString description; + QVariant value; + QVariant oldValue; + /*! The string-to-value correspondence list of the property.*/ + Property::ListData* listData; +// QMap<QString, QVariant> *valueList; + QString icon; + + bool changed : 1; + bool storable : 1; + bool readOnly : 1; + bool visible : 1; + int autosync; + QMap<QCString, QVariant> options; + + CustomProperty *custom; + //! Flag used to allow CustomProperty to use setValue() + bool useCustomProperty; + + //! Used when a single set is assigned for the property + QGuardedPtr<Set> set; + //! Used when multiple sets are assigned for the property + QPtrDict< QGuardedPtr<Set> > *sets; +// QValueList<Set*> sets; + + Property *parent; + QValueList<Property*> *children; + //! list of properties with the same name (when intersecting buffers) + QValueList<Property*> *relatedProperties; + + int sortingKey; +}; +} + +using namespace KoProperty; + +///////////////////////////////////////////////////////////////// + +Property::ListData::ListData(const QStringList& keys_, const QStringList& names_) + : names(names_) +// , fixed(true) +{ + setKeysAsStringList(keys_); +} + +Property::ListData::ListData(const QValueList<QVariant> keys_, const QStringList& names_) + : keys(keys_), names(names_) +// , fixed(true) +{ +} + +Property::ListData::ListData() +// : fixed(true) +{ +} + +Property::ListData::~ListData() +{ +} + +void Property::ListData::setKeysAsStringList(const QStringList& list) +{ + keys.clear(); + for (QStringList::ConstIterator it = list.constBegin(); it!=list.constEnd(); ++it) { + keys.append(*it); + } +} + +QStringList Property::ListData::keysAsStringList() const +{ + QStringList result; + for (QValueList<QVariant>::ConstIterator it = keys.constBegin(); it!=keys.constEnd(); ++it) { + result.append((*it).toString()); + } + return result; +} + +///////////////////////////////////////////////////////////////// + +/* +KOPROPERTY_EXPORT QMap<QString, QVariant> +KoProperty::createValueListFromStringLists(const QStringList &keys, const QStringList &values) +{ + QMap<QString, QVariant> map; + if(keys.count() != values.count()) + return map; + + QStringList::ConstIterator valueIt = values.begin(); + QStringList::ConstIterator endIt = keys.constEnd(); + for(QStringList::ConstIterator it = keys.begin(); it != endIt; ++it, ++valueIt) + map.insert( *it, *valueIt); + + return map; +} +*/ + + +Property::Property(const QCString &name, const QVariant &value, + const QString &caption, const QString &description, + int type, Property* parent) + : d( new PropertyPrivate() ) +{ + d->name = name; + d->setCaptionForDisplaying(caption); + d->description = description; + + if(type == Auto) + d->type = value.type(); + else + d->type = type; + + d->custom = FactoryManager::self()->createCustomProperty(this); + + if (parent) + parent->addChild(this); + setValue(value, false); +} + +Property::Property(const QCString &name, const QStringList &keys, const QStringList &strings, + const QVariant &value, const QString &caption, const QString &description, + int type, Property* parent) + : d( new PropertyPrivate() ) +{ + d->name = name; + d->setCaptionForDisplaying(caption); + d->description = description; + d->type = type; + setListData(keys, strings); + + d->custom = FactoryManager::self()->createCustomProperty(this); + + if (parent) + parent->addChild(this); + setValue(value, false); +} + +Property::Property(const QCString &name, ListData* listData, + const QVariant &value, const QString &caption, const QString &description, + int type, Property* parent) + : d( new PropertyPrivate() ) +{ + d->name = name; + d->setCaptionForDisplaying(caption); + d->description = description; + d->type = type; + d->listData = listData; + + d->custom = FactoryManager::self()->createCustomProperty(this); + + if (parent) + parent->addChild(this); + setValue(value, false); +} + +Property::Property() + : d( new PropertyPrivate() ) +{ +} + +Property::Property(const Property &prop) + : d( new PropertyPrivate() ) +{ + *this = prop; +} + +Property::~Property() +{ + delete d; + d = 0; +} + +QCString +Property::name() const +{ + return d->name; +} + +void +Property::setName(const QCString &name) +{ + d->name = name; +} + +QString +Property::caption() const +{ + return d->caption ? *d->caption : d->captionForDisplaying; +} + +QString +Property::captionForDisplaying() const +{ + return d->captionForDisplaying; +} + +void +Property::setCaption(const QString &caption) +{ + d->setCaptionForDisplaying(caption); +} + +QString +Property::description() const +{ + return d->description; +} + +void +Property::setDescription(const QString &desc) +{ + d->description = desc; +} + +int +Property::type() const +{ + return d->type; +} + +void +Property::setType(int type) +{ + d->type = type; +} + +QString +Property::icon() const +{ + return d->icon; +} + +void +Property::setIcon(const QString &icon) +{ + d->icon = icon; +} + +QVariant +Property::value() const +{ + if(d->custom && d->custom->handleValue()) + return d->custom->value(); + return d->value; +} + +QVariant +Property::oldValue() const +{ +/* if(d->oldValue.isNull()) + return value(); + else*/ + return d->oldValue; +} + +void +Property::setValue(const QVariant &value, bool rememberOldValue, bool useCustomProperty) +{ + if (d->name.isEmpty()) { + kopropertywarn << "Property::setValue(): COULD NOT SET value to a null property" << endl; + return; + } + QVariant currentValue = this->value(); + const QVariant::Type t = currentValue.type(); + const QVariant::Type newt = value.type(); +// kopropertydbg << d->name << " : setValue('" << value.toString() << "' type=" << type() << ")" << endl; + if (t != newt && !currentValue.isNull() && !value.isNull() + && !( (t==QVariant::Int && newt==QVariant::UInt) + || (t==QVariant::UInt && newt==QVariant::Int) + || (t==QVariant::CString && newt==QVariant::String) + || (t==QVariant::String && newt==QVariant::CString) + || (t==QVariant::ULongLong && newt==QVariant::LongLong) + || (t==QVariant::LongLong && newt==QVariant::ULongLong) + )) { + kopropertywarn << "Property::setValue(): INCOMPATIBLE TYPES! old=" << currentValue + << " new=" << value << endl; + } + + //1. Check if the value should be changed + bool ch; + if (t == QVariant::DateTime + || t == QVariant::Time) { + //for date and datetime types: compare with strings, because there + //can be miliseconds difference + ch = (currentValue.toString() != value.toString()); + } + else if (t == QVariant::String || t==QVariant::CString) { + //property is changed for string type, + //if one of value is empty and other isn't.. + ch = ( (currentValue.toString().isEmpty() != value.toString().isEmpty()) + //..or both are not empty and values differ + || (!currentValue.toString().isEmpty() && !value.toString().isEmpty() && currentValue != value) ); + } + else if (t == QVariant::Invalid && newt == QVariant::Invalid) + ch = false; + else + ch = (currentValue != value); + + if (!ch) + return; + + //2. Then change it, and store old value if necessary + if(rememberOldValue) { + if(!d->changed) + d->oldValue = currentValue; + d->changed = true; + } + else { + d->oldValue = QVariant(); // clear old value + d->changed = false; + } + QVariant prevValue; + if(d->custom && useCustomProperty) { + d->custom->setValue(value, rememberOldValue); + prevValue = d->custom->value(); + } + else + prevValue = currentValue; + + if (!d->custom || !useCustomProperty || !d->custom->handleValue()) + d->value = value; + + emitPropertyChanged(); // called as last step in this method! +} + +void +Property::resetValue() +{ + d->changed = false; + bool cleared = false; + if (d->set) + d->set->informAboutClearing(cleared); //inform me about possibly clearing the property sets + setValue(oldValue(), false); + if (cleared) + return; //property set has been cleared: no further actions make sense as 'this' is dead + + // maybe parent prop is also unchanged now + if(d->parent && d->parent->value() == d->parent->oldValue()) + d->parent->d->changed = false; + + if (d->sets) { + for (QPtrDictIterator< QGuardedPtr<Set> > it(*d->sets); it.current(); ++it) { + if (it.current()) //may be destroyed in the meantime + emit (*it.current())->propertyReset(**it.current(), *this); + } + } + else if (d->set) { + emit d->set->propertyReset(*d->set, *this); + } +} + +//const QMap<QString, QVariant>* +Property::ListData* +Property::listData() const +{ + return d->listData; +} + +void +Property::setListData(ListData* list) //const QMap<QString, QVariant> &list) +{ +// if(!d->valueList) +// d->valueList = new QMap<QString, QVariant>(); + if (list == d->listData) + return; + delete d->listData; + d->listData = list; +} + +void +Property::setListData(const QStringList &keys, const QStringList &names) +{ + ListData* list = new ListData(keys, names); + setListData(list); + +// if(!d->valueList) +// d->valueList = new QMap<QString, QVariant>(); +// *(d->valueList) = createValueListFromStringLists(keys, values); +} + +//////////////////////////////////////////////////////////////// + +bool +Property::isNull() const +{ + return d->name.isEmpty(); +} + +bool +Property::isModified() const +{ + return d->changed; +} + +void +Property::clearModifiedFlag() +{ + d->changed = false; +} + +bool +Property::isReadOnly() const +{ + return d->readOnly; +} + +void +Property::setReadOnly(bool readOnly) +{ + d->readOnly = readOnly; +} + +bool +Property::isVisible() const +{ + return d->visible; +} + +void +Property::setVisible(bool visible) +{ + d->visible = visible; +} + +int +Property::autoSync() const +{ + return d->autosync; +} + +void +Property::setAutoSync(int sync) +{ + d->autosync = sync; +} + +bool +Property::isStorable() const +{ + return d->storable; +} + +void +Property::setStorable(bool storable) +{ + d->storable = storable; +} + +void +Property::setOption(const char* name, const QVariant& val) +{ + d->options[name] = val; +} + +QVariant +Property::option(const char* name) const +{ + if (d->options.contains(name)) + return d->options[name]; + return QVariant(); +} + +bool +Property::hasOptions() const +{ + return !d->options.isEmpty(); +} + +///////////////////////////////////////////////////////////////// + +Property::operator bool () const +{ + return !isNull(); +} + +const Property& +Property::operator= (const QVariant& val) +{ + setValue(val); + return *this; +} + +const Property& +Property::operator= (const Property &property) +{ + if(&property == this) + return *this; + + if(d->listData) { + delete d->listData; + d->listData = 0; + } + if(d->children) { + delete d->children; + d->children = 0; + } + if(d->relatedProperties) { + delete d->relatedProperties; + d->relatedProperties = 0; + } + if(d->custom) { + delete d->custom; + d->custom = 0; + } + + d->name = property.d->name; + d->setCaptionForDisplaying(property.captionForDisplaying()); + d->description = property.d->description; + d->type = property.d->type; + + d->icon = property.d->icon; + d->autosync = property.d->autosync; + d->visible = property.d->visible; + d->storable = property.d->storable; + d->readOnly = property.d->readOnly; + d->options = property.d->options; + + if(property.d->listData) { + d->listData = new ListData(*property.d->listData); //QMap<QString, QVariant>(*(property.d->valueList)); + } + if(property.d->custom) { + d->custom = FactoryManager::self()->createCustomProperty(this); + // updates all children value, using CustomProperty + setValue(property.value()); + } + else { + d->value = property.d->value; + if(property.d->children) { + // no CustomProperty (should never happen), simply copy all children + d->children = new QValueList<Property*>(); + QValueList<Property*>::ConstIterator endIt = property.d->children->constEnd(); + for(QValueList<Property*>::ConstIterator it = property.d->children->constBegin(); it != endIt; ++it) { + Property *child = new Property( *(*it) ); + addChild(child); + } + } + } + + if(property.d->relatedProperties) { + d->relatedProperties = new QValueList<Property*>( *(property.d->relatedProperties)); + } + + // update these later because they may have been changed when creating children + d->oldValue = property.d->oldValue; + d->changed = property.d->changed; + d->sortingKey = property.d->sortingKey; + + return *this; +} + +bool +Property::operator ==(const Property &prop) const +{ + return ((d->name == prop.d->name) && (value() == prop.value())); +} + +///////////////////////////////////////////////////////////////// + +const QValueList<Property*>* +Property::children() const +{ + return d->children; +} + +Property* +Property::child(const QCString &name) +{ + QValueList<Property*>::ConstIterator endIt = d->children->constEnd(); + for(QValueList<Property*>::ConstIterator it = d->children->constBegin(); it != endIt; ++it) { + if((*it)->name() == name) + return *it; + } + return 0; +} + +Property* +Property::parent() const +{ + return d->parent; +} + +void +Property::addChild(Property *prop) +{ + if (!prop) + return; + + if(!d->children || qFind( d->children->begin(), d->children->end(), prop) == d->children->end()) { // not in our list + if(!d->children) + d->children = new QValueList<Property*>(); + d->children->append(prop); + prop->setSortingKey(d->children->count()); + prop->d->parent = this; + } + else { + kopropertywarn << "Property::addChild(): property \"" << name() + << "\": child property \"" << prop->name() << "\" already added" << endl; + return; + } +} + +void +Property::addSet(Set *set) +{ + if (!set) + return; + + if (!d->set) {//simple case + d->set = set; + return; + } + if ((Set*)d->set==set) + return; + QGuardedPtr<Set> *pset = d->sets ? d->sets->find(set) : 0; + if (pset && (Set*)*pset == set) + return; + if (!d->sets) { + d->sets = new QPtrDict< QGuardedPtr<Set> >( 101 ); + d->sets->setAutoDelete(true); + } + + d->sets->replace(set, new QGuardedPtr<Set>( set )); + +// QValueList<Set*>::iterator it = qFind( d->sets.begin(), d->sets.end(), set); +// if(it == d->sets.end()) // not in our list +// d->sets.append(set); +} + +const QValueList<Property*>* +Property::related() const +{ + return d->relatedProperties; +} + +void +Property::addRelatedProperty(Property *property) +{ + if(!d->relatedProperties) + d->relatedProperties = new QValueList<Property*>(); + + QValueList<Property*>::iterator it = qFind( d->relatedProperties->begin(), d->relatedProperties->end(), property); + if(it == d->relatedProperties->end()) // not in our list + d->relatedProperties->append(property); +} + +CustomProperty* +Property::customProperty() const +{ + return d->custom; +} + +void +Property::setCustomProperty(CustomProperty *prop) +{ + d->custom = prop; +} + +int Property::sortingKey() const +{ + return d->sortingKey; +} + +void Property::setSortingKey(int key) +{ + d->sortingKey = key; +} + +void Property::emitPropertyChanged() +{ + if (d->sets) { + for (QPtrDictIterator< QGuardedPtr<Set> > it(*d->sets); it.current(); ++it) { + if (it.current()) {//may be destroyed in the meantime + emit (*it.current())->propertyChangedInternal(**it.current(), *this); + emit (*it.current())->propertyChanged(**it.current(), *this); + } + } + } + else if (d->set) { + //if the slot connect with that signal may call set->clear() - that's + //the case e.g. at kexi/plugins/{macros|scripting}/* - this Property + //may got destroyed ( see Set::removeProperty(Property*) ) while we are + //still on it. So, if we try to access ourself/this once the signal + //got emitted we may end in a very hard to reproduce crash. So, the + //emit should happen as last step in this method! + emit d->set->propertyChangedInternal(*d->set, *this); + emit d->set->propertyChanged(*d->set, *this); + } +} + +///////////////////////////////////////////////////////////////// + +void +Property::debug() +{ + QString dbg = "Property( name='" + QString(d->name) + "' desc='" + d->description + + "' val=" + (value().isValid() ? value().toString() : "<INVALID>"); + if (!d->oldValue.isValid()) + dbg += (", oldVal='" + d->oldValue.toString() + '\''); + dbg += (QString(d->changed ? " " : " un") + "changed"); + dbg += (d->visible ? " visible" : " hidden"); + dbg+=" )"; + + kopropertydbg << dbg << endl; +} |