summaryrefslogtreecommitdiffstats
path: root/lib/koproperty/property.cpp
diff options
context:
space:
mode:
authortpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-01-20 01:29:50 +0000
committertpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-01-20 01:29:50 +0000
commit8362bf63dea22bbf6736609b0f49c152f975eb63 (patch)
tree0eea3928e39e50fae91d4e68b21b1e6cbae25604 /lib/koproperty/property.cpp
downloadkoffice-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.cpp778
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;
+}