lib

set.cpp

00001 /* This file is part of the KDE project
00002    Copyright (C) 2004 Cedric Pasteur <cedric.pasteur@free.fr>
00003    Copyright (C) 2004 Alexander Dymo <cloudtemple@mskat.net>
00004    Copyright (C) 2004-2006 Jaroslaw Staniek <js@iidea.pl>
00005 
00006    This library is free software; you can redistribute it and/or
00007    modify it under the terms of the GNU Library General Public
00008    License as published by the Free Software Foundation; either
00009    version 2 of the License, or (at your option) any later version.
00010 
00011    This library is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014    Library General Public License for more details.
00015 
00016    You should have received a copy of the GNU Library General Public License
00017    along with this library; see the file COPYING.LIB.  If not, write to
00018    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00019  * Boston, MA 02110-1301, USA.
00020 */
00021 
00022 #include "set.h"
00023 #include "property.h"
00024 #include "utils.h"
00025 
00026 #include <qapplication.h>
00027 #include <qasciidict.h>
00028 //#include <qvaluelist.h>
00029 
00030 #include <kdebug.h>
00031 #include <klocale.h>
00032 
00033 typedef QMap<QCString, QValueList<QCString> > StringListMap;
00034 typedef QMapIterator<QCString, QStringList> StringListMapIterator;
00035 
00036 namespace KoProperty {
00037 
00039 static Property Set_nonConstNull;
00040 
00042 class SetPrivate
00043 {
00044     public:
00045         SetPrivate() :
00046             dict(101, false), 
00047             readOnly(false),
00048             informAboutClearing(0)
00049         {}
00050         ~SetPrivate(){}
00051 
00052     //dict of properties in form name: property
00053     Property::Dict dict;
00054 //  PropertyList properties;
00055     //groups of properties:
00056     // list of group name: (list of property names)
00057     StringListMap propertiesOfGroup;
00058     QValueList<QCString> groupNames;
00059     QMap<QCString, QString>  groupDescriptions;
00060     QMap<QCString, QString>  groupIcons;
00061     // map of property: group
00062     QMap<Property*, QCString> groupForProperty;
00063 
00064     bool ownProperty : 1;
00065     bool readOnly : 1;
00066 //  static Property nonConstNull;
00067     QCString prevSelection;
00068     QString typeName;
00069 
00072     bool* informAboutClearing;
00073 
00074     inline KoProperty::Property& property(const QCString &name) const
00075     {
00076         KoProperty::Property *p = dict.find(name);
00077         if (p)
00078             return *p;
00079         Set_nonConstNull.setName(0); //to ensure returned property is null
00080         kopropertywarn << "Set::property(): PROPERTY \"" << name << "\" NOT FOUND" << endl;
00081         return Set_nonConstNull;
00082     }
00083 };
00084 
00085 }
00086 
00087 using namespace KoProperty;
00088 
00089 //Set::Iterator class
00090 Set::Iterator::Iterator(const Set &set)
00091 {
00092     iterator = new Property::DictIterator(set.d->dict);
00093 }
00094 
00095 Set::Iterator::~Iterator()
00096 {
00097     delete iterator;
00098 }
00099 
00100 void
00101 Set::Iterator::operator ++()
00102 {
00103     ++(*iterator);
00104 }
00105 
00106 Property*
00107 Set::Iterator::operator *() const
00108 {
00109     return current();
00110 }
00111 
00112 QCString
00113 Set::Iterator::currentKey() const
00114 {
00115     if (iterator)
00116         return iterator->currentKey();
00117 
00118     return QCString();
00119 }
00120 
00121 Property*
00122 Set::Iterator::current() const
00123 {
00124     if(iterator)
00125         return iterator->current();
00126 
00127     return 0;
00128 }
00129 
00131 
00132 Set::Set(QObject *parent, const QString &typeName)
00133 : QObject(parent, typeName.latin1())
00134 {
00135     d = new SetPrivate();
00136     d->ownProperty = true;
00137     d->groupDescriptions.insert("common", i18n("General properties", "General"));
00138     d->typeName = typeName;
00139 }
00140 
00141 
00142 Set::Set(const Set &set)
00143  : QObject(0 /* implicit sharing the parent is dangerous */, set.name())
00144 {
00145     d = new SetPrivate();
00146     *this = set;
00147 }
00148 
00149 Set::Set(bool propertyOwner)
00150  : QObject(0, 0)
00151 {
00152     d = new SetPrivate();
00153     d->ownProperty = propertyOwner;
00154     d->groupDescriptions.insert("common", i18n("General properties", "General"));
00155 }
00156 
00157 Set::~Set()
00158 {
00159     emit aboutToBeCleared();
00160     emit aboutToBeDeleted();
00161     clear();
00162     delete d;
00163 }
00164 
00166 
00167 void
00168 Set::addPropertyInternal(Property *property, QCString group, bool updateSortingKey)
00169 {
00170     if (group.isEmpty())
00171         group = "common";
00172     if (property == 0) {
00173         kopropertywarn << "Set::addProperty(): property == 0" << endl; 
00174         return;
00175     }
00176     if (property->name().isEmpty()) {
00177         kopropertywarn << "Set::addProperty(): COULD NOT ADD NULL PROPERTY" << endl; 
00178         return;
00179     }
00180 
00181     Property *p = d->dict.find(property->name());
00182     if(p) {
00183         p->addRelatedProperty(property);
00184     }
00185     else {
00186         d->dict.insert(property->name(), property);
00187         addToGroup(group, property);
00188     }
00189 
00190     property->addSet(this);
00191     if (updateSortingKey)
00192         property->setSortingKey( d->dict.count() );
00193 }
00194 
00195 void
00196 Set::addProperty(Property *property, QCString group)
00197 {
00198     addPropertyInternal(property, group, true);
00199 }
00200 
00201 void
00202 Set::removeProperty(Property *property)
00203 {
00204     if(!property)
00205         return;
00206 
00207     Property *p = d->dict.take(property->name());
00208     removeFromGroup(p);
00209     if(d->ownProperty) {
00210         emit aboutToDeleteProperty(*this, *p);
00211         delete p;
00212     }
00213 }
00214 
00215 void
00216 Set::removeProperty(const QCString &name)
00217 {
00218     if(name.isNull())
00219         return;
00220 
00221     Property *p = d->dict.find(name);
00222     removeProperty(p);
00223 }
00224 
00225 void
00226 Set::clear()
00227 {
00228     if (d->informAboutClearing)
00229         *d->informAboutClearing = true;
00230     d->informAboutClearing = 0;
00231     aboutToBeCleared();
00232     d->propertiesOfGroup.clear();
00233     d->groupNames.clear();
00234     d->groupForProperty.clear();
00235     d->groupDescriptions.clear();
00236     d->groupIcons.clear();
00237     Property::DictIterator it(d->dict);
00238     while (it.current())
00239         removeProperty( it.current() );
00240 }
00241 
00242 void
00243 Set::informAboutClearing(bool& cleared)
00244 {
00245     cleared = false;
00246     d->informAboutClearing = &cleared;
00247 }
00248 
00250 
00251 void
00252 Set::addToGroup(const QCString &group, Property *property)
00253 {
00254     if(!property)
00255         return;
00256 
00257     //do not add the same property to the group twice
00258     if(d->groupForProperty.contains(property) && (d->groupForProperty[property] == group))
00259         return;
00260 
00261     if(!d->propertiesOfGroup.contains(group)) { // group doesn't exist
00262         QValueList<QCString> l;
00263         l.append(property->name());
00264         d->propertiesOfGroup.insert(group, l);
00265         d->groupNames.append(group);
00266     }
00267     else {
00268         d->propertiesOfGroup[group].append(property->name());
00269     }
00270     d->groupForProperty.insert(property, group);
00271 }
00272 
00273 void
00274 Set::removeFromGroup(Property *property)
00275 {
00276     if(!property)
00277         return;
00278     QCString group = d->groupForProperty[property];
00279     d->propertiesOfGroup[group].remove(property->name());
00280     if (d->propertiesOfGroup[group].isEmpty()) {
00281         //remove group as well
00282         d->propertiesOfGroup.remove(group);
00283         QValueListIterator<QCString> it = d->groupNames.find(group);
00284         if (it != d->groupNames.end()) {
00285             d->groupNames.remove(it);
00286         }
00287     }
00288     d->groupForProperty.remove(property);
00289 }
00290 
00291 const QValueList<QCString>&
00292 Set::groupNames() const
00293 {
00294     return d->groupNames;
00295 }
00296 
00297 const QValueList<QCString>&
00298 Set::propertyNamesForGroup(const QCString &group) const
00299 {
00300     return d->propertiesOfGroup[group];
00301 }
00302 
00303 void
00304 Set::setGroupDescription(const QCString &group, const QString& desc)
00305 {
00306     d->groupDescriptions[group] = desc;
00307 }
00308 
00309 QString
00310 Set::groupDescription(const QCString &group) const
00311 {
00312     if(d->groupDescriptions.contains(group))
00313         return d->groupDescriptions[group];
00314     return group;
00315 }
00316 
00317 void
00318 Set::setGroupIcon(const QCString &group, const QString& icon)
00319 {
00320     d->groupIcons[group] = icon;
00321 }
00322 
00323 QString
00324 Set::groupIcon(const QCString &group) const
00325 {
00326     return d->groupIcons[group];
00327 }
00328 
00330 
00331 uint
00332 Set::count() const
00333 {
00334     return d->dict.count();
00335 }
00336 
00337 bool
00338 Set::isEmpty() const
00339 {
00340     return d->dict.isEmpty();
00341 }
00342 
00343 bool
00344 Set::isReadOnly() const
00345 {
00346     return d->readOnly;
00347 }
00348 
00349 void
00350 Set::setReadOnly(bool readOnly)
00351 {
00352     d->readOnly = readOnly;
00353 }
00354 
00355 bool
00356 Set::contains(const QCString &name) const
00357 {
00358     return d->dict.find(name);
00359 }
00360 
00361 Property&
00362 Set::property(const QCString &name) const
00363 {
00364     return d->property(name);
00365 }
00366 
00367 Property&
00368 Set::operator[](const QCString &name) const
00369 {
00370     return d->property(name);
00371 }
00372 
00373 const Set&
00374 Set::operator= (const Set &set)
00375 {
00376     if(&set == this)
00377         return *this;
00378 
00379     clear();
00380 
00381     d->ownProperty = set.d->ownProperty;
00382     d->prevSelection = set.d->prevSelection;
00383     d->groupDescriptions = set.d->groupDescriptions;
00384 
00385     // Copy all properties in the list
00386     for(Property::DictIterator it(set.d->dict); it.current(); ++it) {
00387         Property *prop = new Property( *it.current() );
00388         addPropertyInternal(prop, set.d->groupForProperty[ it.current() ], 
00389             false  );
00390     }
00391 
00392     return *this;
00393 }
00394 
00395 void
00396 Set::changeProperty(const QCString &property, const QVariant &value)
00397 {
00398     Property *p = d->dict[property];
00399     if(p)
00400         p->setValue(value);
00401 }
00402 
00404 
00405 void
00406 Set::debug()
00407 {
00408     //kopropertydbg << "List: typeName='" << m_typeName << "'" << endl;
00409     if(d->dict.isEmpty()) {
00410         kopropertydbg << "<EMPTY>" << endl;
00411         return;
00412     }
00413     kopropertydbg << d->dict.count() << " properties:" << endl;
00414 
00415     for(Property::DictIterator it(d->dict); it.current(); ++it)
00416         it.current()->debug();
00417 }
00418 
00419 QCString
00420 Set::prevSelection() const
00421 {
00422     return d->prevSelection;
00423 }
00424 
00425 void
00426 Set::setPrevSelection(const QCString &prevSelection)
00427 {
00428     d->prevSelection = prevSelection;
00429 }
00430 
00431 QString
00432 Set::typeName() const
00433 {
00434     return d->typeName;
00435 }
00436 
00438 
00439 Buffer::Buffer()
00440     :Set(false)
00441 {
00442     connect( this, SIGNAL( propertyChanged( KoProperty::Set&, KoProperty::Property& ) ),
00443              this, SLOT(intersectedChanged( KoProperty::Set&, KoProperty::Property& ) ) );
00444 
00445     connect( this, SIGNAL( propertyReset( KoProperty::Set&, KoProperty::Property& ) ),
00446              this, SLOT(intersectedReset( KoProperty::Set&, KoProperty::Property& ) ) );
00447 }
00448 
00449 Buffer::Buffer(const Set *set)
00450     :Set(false)
00451 {
00452     connect( this, SIGNAL( propertyChanged( KoProperty::Set&, KoProperty::Property& ) ),
00453              this, SLOT(intersectedChanged( KoProperty::Set&, KoProperty::Property& ) ) );
00454 
00455     connect( this, SIGNAL( propertyReset( KoProperty::Set&, KoProperty::Property& ) ),
00456              this, SLOT(intersectedReset( KoProperty::Set&, KoProperty::Property& ) ) );
00457 
00458     initialSet( set );
00459 }
00460 
00461 void Buffer::initialSet(const Set *set)
00462 {
00463     //deep copy of set
00464     for(Property::DictIterator it(set->d->dict); it.current(); ++it) {
00465         Property *prop = new Property( *it.current() );
00466         QCString group = set->d->groupForProperty[it.current()];
00467         QString groupDesc = set->d->groupDescriptions[ group ];
00468         setGroupDescription( group, groupDesc );
00469         addProperty( prop, group );
00470         prop->addRelatedProperty( it.current() );
00471     }
00472 }
00473 
00474 void Buffer::intersect(const Set *set)
00475 {
00476     if ( d->dict.isEmpty() )
00477     {
00478         initialSet( set );
00479         return;
00480     }
00481 
00482      for(Property::DictIterator it(d->dict); it.current(); ++it) {
00483         const char* key = it.current()->name();
00484         if ( Property *property =  set->d->dict[ key ] )
00485         {
00486                 blockSignals( true );
00487                 it.current()->resetValue();
00488                 it.current()->addRelatedProperty( property );
00489                 blockSignals( false );
00490         }
00491         else
00492             removeProperty( key );
00493     }
00494 }
00495 
00496 void Buffer::intersectedChanged(KoProperty::Set& set, KoProperty::Property& prop)
00497 {
00498     Q_UNUSED(set);
00499     QCString propertyName = prop.name();
00500     if ( !contains( propertyName ) )
00501         return;
00502 
00503     const QValueList<Property*> *props = prop.related();
00504     QValueList<Property*>::const_iterator it = props->begin();
00505     for ( ; it != props->end(); ++it ) {
00506         ( *it )->setValue( prop.value(), false );
00507     }
00508 }
00509 
00510 void Buffer::intersectedReset(KoProperty::Set& set, KoProperty::Property& prop)
00511 {
00512     Q_UNUSED(set);
00513     QCString propertyName = prop.name();
00514     if ( !contains( propertyName ) )
00515         return;
00516 
00517     const QValueList<Property*> *props = prop.related();
00518     QValueList<Property*>::const_iterator it = props->begin();
00519     for ( ; it != props->end(); ++it )  {
00520         ( *it )->setValue( prop.value(), false );
00521     }
00522 }
00523 
00525 
00526 QMap<QCString, QVariant> KoProperty::propertyValues(const Set& set)
00527 {
00528     QMap<QCString, QVariant> result;
00529     for (Set::Iterator it(set); it.current(); ++it)
00530         result.insert( it.currentKey(), it.current()->value() );
00531     
00532     return result;
00533 }
00534 
00535 #include "set.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys