/* This file is part of the KDE project Copyright (C) 2004 Cedric Pasteur Copyright (C) 2004 Alexander Dymo Copyright (C) 2004-2006 Jaroslaw Staniek 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 "set.h" #include "property.h" #include "utils.h" #include #include //#include #include #include typedef TQMap > StringListMap; typedef TQMapIterator StringListMapIterator; namespace KoProperty { //! @internal static Property Set_nonConstNull; //! @internal class SetPrivate { public: SetPrivate() : dict(101, false), readOnly(false), informAboutClearing(0) {} ~SetPrivate(){} //dict of properties in form name: property Property::Dict dict; // PropertyList properties; //groups of properties: // list of group name: (list of property names) StringListMap propertiesOfGroup; TQValueList groupNames; TQMap groupDescriptions; TQMap groupIcons; // map of property: group TQMap groupForProperty; bool ownProperty : 1; bool readOnly : 1; // static Property nonConstNull; TQCString prevSelection; TQString typeName; //! Used in Set::informAboutClearing(Property*) to declare that the property wants //! to be informed that the set has been cleared (all properties are deleted) bool* informAboutClearing; inline KoProperty::Property& property(const TQCString &name) const { KoProperty::Property *p = dict.find(name); if (p) return *p; Set_nonConstNull.setName(0); //to ensure returned property is null kopropertywarn << "Set::property(): PROPERTY \"" << name << "\" NOT FOUND" << endl; return Set_nonConstNull; } }; } using namespace KoProperty; //Set::Iterator class Set::Iterator::Iterator(const Set &set) { iterator = new Property::DictIterator(set.d->dict); } Set::Iterator::~Iterator() { delete iterator; } void Set::Iterator::operator ++() { ++(*iterator); } Property* Set::Iterator::operator *() const { return current(); } TQCString Set::Iterator::currentKey() const { if (iterator) return iterator->currentKey(); return TQCString(); } Property* Set::Iterator::current() const { if(iterator) return iterator->current(); return 0; } ////////////////////////////////////////////// Set::Set(TQObject *parent, const TQString &typeName) : TQObject(parent, typeName.latin1()) { d = new SetPrivate(); d->ownProperty = true; d->groupDescriptions.insert("common", i18n("General properties", "General")); d->typeName = typeName; } Set::Set(const Set &set) : TQObject(0 /* implicit sharing the parent is dangerous */, set.name()) { d = new SetPrivate(); *this = set; } Set::Set(bool propertyOwner) : TQObject(0, 0) { d = new SetPrivate(); d->ownProperty = propertyOwner; d->groupDescriptions.insert("common", i18n("General properties", "General")); } Set::~Set() { emit aboutToBeCleared(); emit aboutToBeDeleted(); clear(); delete d; } ///////////////////////////////////////////////////// void Set::addPropertyInternal(Property *property, TQCString group, bool updateSortingKey) { if (group.isEmpty()) group = "common"; if (property == 0) { kopropertywarn << "Set::addProperty(): property == 0" << endl; return; } if (property->name().isEmpty()) { kopropertywarn << "Set::addProperty(): COULD NOT ADD NULL PROPERTY" << endl; return; } Property *p = d->dict.find(property->name()); if(p) { p->addRelatedProperty(property); } else { d->dict.insert(property->name(), property); addToGroup(group, property); } property->addSet(this); if (updateSortingKey) property->setSortingKey( d->dict.count() ); } void Set::addProperty(Property *property, TQCString group) { addPropertyInternal(property, group, true); } void Set::removeProperty(Property *property) { if(!property) return; Property *p = d->dict.take(property->name()); removeFromGroup(p); if(d->ownProperty) { emit aboutToDeleteProperty(*this, *p); delete p; } } void Set::removeProperty(const TQCString &name) { if(name.isNull()) return; Property *p = d->dict.find(name); removeProperty(p); } void Set::clear() { if (d->informAboutClearing) *d->informAboutClearing = true; d->informAboutClearing = 0; aboutToBeCleared(); d->propertiesOfGroup.clear(); d->groupNames.clear(); d->groupForProperty.clear(); d->groupDescriptions.clear(); d->groupIcons.clear(); Property::DictIterator it(d->dict); while (it.current()) removeProperty( it.current() ); } void Set::informAboutClearing(bool& cleared) { cleared = false; d->informAboutClearing = &cleared; } ///////////////////////////////////////////////////// void Set::addToGroup(const TQCString &group, Property *property) { if(!property) return; //do not add the same property to the group twice if(d->groupForProperty.contains(property) && (d->groupForProperty[property] == group)) return; if(!d->propertiesOfGroup.contains(group)) { // group doesn't exist TQValueList l; l.append(property->name()); d->propertiesOfGroup.insert(group, l); d->groupNames.append(group); } else { d->propertiesOfGroup[group].append(property->name()); } d->groupForProperty.insert(property, group); } void Set::removeFromGroup(Property *property) { if(!property) return; TQCString group = d->groupForProperty[property]; d->propertiesOfGroup[group].remove(property->name()); if (d->propertiesOfGroup[group].isEmpty()) { //remove group as well d->propertiesOfGroup.remove(group); TQValueListIterator it = d->groupNames.find(group); if (it != d->groupNames.end()) { d->groupNames.remove(it); } } d->groupForProperty.remove(property); } const TQValueList& Set::groupNames() const { return d->groupNames; } const TQValueList& Set::propertyNamesForGroup(const TQCString &group) const { return d->propertiesOfGroup[group]; } void Set::setGroupDescription(const TQCString &group, const TQString& desc) { d->groupDescriptions[group] = desc; } TQString Set::groupDescription(const TQCString &group) const { if(d->groupDescriptions.contains(group)) return d->groupDescriptions[group]; return group; } void Set::setGroupIcon(const TQCString &group, const TQString& icon) { d->groupIcons[group] = icon; } TQString Set::groupIcon(const TQCString &group) const { return d->groupIcons[group]; } ///////////////////////////////////////////////////// uint Set::count() const { return d->dict.count(); } bool Set::isEmpty() const { return d->dict.isEmpty(); } bool Set::isReadOnly() const { return d->readOnly; } void Set::setReadOnly(bool readOnly) { d->readOnly = readOnly; } bool Set::contains(const TQCString &name) const { return d->dict.find(name); } Property& Set::property(const TQCString &name) const { return d->property(name); } Property& Set::operator[](const TQCString &name) const { return d->property(name); } const Set& Set::operator= (const Set &set) { if(&set == this) return *this; clear(); d->ownProperty = set.d->ownProperty; d->prevSelection = set.d->prevSelection; d->groupDescriptions = set.d->groupDescriptions; // Copy all properties in the list for(Property::DictIterator it(set.d->dict); it.current(); ++it) { Property *prop = new Property( *it.current() ); addPropertyInternal(prop, set.d->groupForProperty[ it.current() ], false /*!updateSortingKey, because the key is already set in Property copy ctor.*/ ); } return *this; } void Set::changeProperty(const TQCString &property, const TQVariant &value) { Property *p = d->dict[property]; if(p) p->setValue(value); } ///////////////////////////////////////////////////// void Set::debug() { //kopropertydbg << "List: typeName='" << m_typeName << "'" << endl; if(d->dict.isEmpty()) { kopropertydbg << "" << endl; return; } kopropertydbg << d->dict.count() << " properties:" << endl; for(Property::DictIterator it(d->dict); it.current(); ++it) it.current()->debug(); } TQCString Set::prevSelection() const { return d->prevSelection; } void Set::setPrevSelection(const TQCString &prevSelection) { d->prevSelection = prevSelection; } TQString Set::typeName() const { return d->typeName; } ///////////////////////////////////////////////////// Buffer::Buffer() :Set(false) { connect( this, TQT_SIGNAL( propertyChanged( KoProperty::Set&, KoProperty::Property& ) ), this, TQT_SLOT(intersectedChanged( KoProperty::Set&, KoProperty::Property& ) ) ); connect( this, TQT_SIGNAL( propertyReset( KoProperty::Set&, KoProperty::Property& ) ), this, TQT_SLOT(intersectedReset( KoProperty::Set&, KoProperty::Property& ) ) ); } Buffer::Buffer(const Set *set) :Set(false) { connect( this, TQT_SIGNAL( propertyChanged( KoProperty::Set&, KoProperty::Property& ) ), this, TQT_SLOT(intersectedChanged( KoProperty::Set&, KoProperty::Property& ) ) ); connect( this, TQT_SIGNAL( propertyReset( KoProperty::Set&, KoProperty::Property& ) ), this, TQT_SLOT(intersectedReset( KoProperty::Set&, KoProperty::Property& ) ) ); initialSet( set ); } void Buffer::initialSet(const Set *set) { //deep copy of set for(Property::DictIterator it(set->d->dict); it.current(); ++it) { Property *prop = new Property( *it.current() ); TQCString group = set->d->groupForProperty[it.current()]; TQString groupDesc = set->d->groupDescriptions[ group ]; setGroupDescription( group, groupDesc ); addProperty( prop, group ); prop->addRelatedProperty( it.current() ); } } void Buffer::intersect(const Set *set) { if ( d->dict.isEmpty() ) { initialSet( set ); return; } for(Property::DictIterator it(d->dict); it.current(); ++it) { const char* key = it.current()->name(); if ( Property *property = set->d->dict[ key ] ) { blockSignals( true ); it.current()->resetValue(); it.current()->addRelatedProperty( property ); blockSignals( false ); } else removeProperty( key ); } } void Buffer::intersectedChanged(KoProperty::Set& set, KoProperty::Property& prop) { Q_UNUSED(set); TQCString propertyName = prop.name(); if ( !contains( propertyName ) ) return; const TQValueList *props = prop.related(); TQValueList::const_iterator it = props->begin(); for ( ; it != props->end(); ++it ) { ( *it )->setValue( prop.value(), false ); } } void Buffer::intersectedReset(KoProperty::Set& set, KoProperty::Property& prop) { Q_UNUSED(set); TQCString propertyName = prop.name(); if ( !contains( propertyName ) ) return; const TQValueList *props = prop.related(); TQValueList::const_iterator it = props->begin(); for ( ; it != props->end(); ++it ) { ( *it )->setValue( prop.value(), false ); } } ////////////////////////////////////////////// TQMap KoProperty::propertyValues(const Set& set) { TQMap result; for (Set::Iterator it(set); it.current(); ++it) result.insert( it.currentKey(), it.current()->value() ); return result; } #include "set.moc"