F:/KPlato/koffice/libs/koproperty/set.cpp

Aller à la documentation de ce fichier.
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 <q3asciidict.h>
00028 #include <QByteArray>
00029 
00030 #include <kdebug.h>
00031 #include <klocale.h>
00032 
00033 typedef QMap<QByteArray, QList<QByteArray> > StringListMap;
00034 typedef QMapIterator<QByteArray, 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         QList<QByteArray>  groupNames;
00059         QMap<QByteArray, QString>  groupDescriptions;
00060         QMap<QByteArray, QString>  groupIcons;
00061         // map of property: group
00062         QMap<Property*, QByteArray> groupForProperty;
00063 
00064         bool ownProperty : 1;
00065         bool readOnly : 1;
00066 //      static Property nonConstNull;
00067         QByteArray prevSelection;
00068         QString typeName;
00069 
00072         bool* informAboutClearing;
00073 
00074         inline KoProperty::Property& property(const QByteArray &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 QByteArray
00113 Set::Iterator::currentKey() const
00114 {
00115         if (iterator)
00116                 return iterator->currentKey();
00117 
00118         return QByteArray();
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)
00134 {
00135         setObjectName(typeName.toLatin1());
00136 
00137         d = new SetPrivate();
00138         d->ownProperty = true;
00139         d->groupDescriptions.insert("common", i18nc("General properties", "General"));
00140         d->typeName = typeName;
00141 }
00142 
00143 
00144 Set::Set(const Set &set)
00145  : QObject(0 /* implicit sharing the parent is dangerous */)
00146 {
00147         setObjectName(set.objectName());
00148         d = new SetPrivate();
00149         *this = set;
00150 }
00151 
00152 Set::Set(bool propertyOwner)
00153  : QObject(0)
00154 {
00155         d = new SetPrivate();
00156         d->ownProperty = propertyOwner;
00157         d->groupDescriptions.insert("common", i18nc("General properties", "General"));
00158 }
00159 
00160 Set::~Set()
00161 {
00162         emit aboutToBeCleared();
00163         emit aboutToBeDeleted();
00164         clear();
00165         delete d;
00166 }
00167 
00169 
00170 void
00171 Set::addPropertyInternal(Property *property, QByteArray group, bool updateSortingKey)
00172 {
00173         if (group.isEmpty())
00174                 group = "common";
00175         if (property == 0) {
00176                 kopropertywarn << "Set::addProperty(): property == 0" << endl; 
00177                 return;
00178         }
00179         if (property->name().isEmpty()) {
00180                 kopropertywarn << "Set::addProperty(): COULD NOT ADD NULL PROPERTY" << endl; 
00181                 return;
00182         }
00183 
00184         Property *p = d->dict.find(property->name());
00185         if(p) {
00186                 p->addRelatedProperty(property);
00187         }
00188         else {
00189                 d->dict.insert(property->name(), property);
00190                 addToGroup(group, property);
00191         }
00192 
00193         property->addSet(this);
00194         if (updateSortingKey)
00195                 property->setSortingKey( d->dict.count() );
00196 }
00197 
00198 void
00199 Set::addProperty(Property *property, QByteArray group)
00200 {
00201         addPropertyInternal(property, group, true);
00202 }
00203 
00204 void
00205 Set::removeProperty(Property *property)
00206 {
00207         if(!property)
00208                 return;
00209 
00210         Property *p = d->dict.take(property->name());
00211         removeFromGroup(p);
00212         if(d->ownProperty) {
00213                 emit aboutToDeleteProperty(*this, *p);
00214                 delete p;
00215         }
00216 }
00217 
00218 void
00219 Set::removeProperty(const QByteArray &name)
00220 {
00221         if(name.isNull())
00222                 return;
00223 
00224         Property *p = d->dict.find(name);
00225         removeProperty(p);
00226 }
00227 
00228 void
00229 Set::clear()
00230 {
00231         if (d->informAboutClearing)
00232                 *d->informAboutClearing = true;
00233         d->informAboutClearing = 0;
00234         aboutToBeCleared();
00235         d->propertiesOfGroup.clear();
00236         d->groupNames.clear();
00237         d->groupForProperty.clear();
00238         d->groupDescriptions.clear();
00239         d->groupIcons.clear();
00240         Property::DictIterator it(d->dict);
00241         while (it.current())
00242                 removeProperty( it.current() );
00243 }
00244 
00245 void
00246 Set::informAboutClearing(bool& cleared)
00247 {
00248         cleared = false;
00249         d->informAboutClearing = &cleared;
00250 }
00251 
00253 
00254 void
00255 Set::addToGroup(const QByteArray &group, Property *property)
00256 {
00257         if(!property)
00258                 return;
00259 
00260         //do not add the same property to the group twice
00261         if(d->groupForProperty.contains(property) && (d->groupForProperty[property] == group))
00262                 return;
00263 
00264         if(!d->propertiesOfGroup.contains(group)) { // group doesn't exist
00265                 QList<QByteArray> l;
00266                 l.append(property->name());
00267                 d->propertiesOfGroup.insert(group, l);
00268                 d->groupNames.append(group);
00269         }
00270         else {
00271                 d->propertiesOfGroup[group].append(property->name());
00272         }
00273         d->groupForProperty.insert(property, group);
00274 }
00275 
00276 void
00277 Set::removeFromGroup(Property *property)
00278 {
00279         if(!property)
00280                 return;
00281         QMap<Property*, QByteArray>::ConstIterator it = d->groupForProperty.find(property);
00282         if (it==d->groupForProperty.constEnd())
00283                 return;
00284         QByteArray group = *it;
00285         QList<QByteArray> propertiesOfGroup = d->propertiesOfGroup[group];
00286         propertiesOfGroup.removeAt( propertiesOfGroup.indexOf(property->name()) );
00287         if (propertiesOfGroup.isEmpty()) {
00288                 //remove group as well
00289                 d->propertiesOfGroup.remove( group );
00290                 const int i = d->groupNames.indexOf(group);
00291                 if (i!=-1)
00292                         d->groupNames.removeAt(i);
00293         }
00294         d->groupForProperty.remove(property);
00295 }
00296 
00297 const QList<QByteArray>&
00298 Set::groupNames() const
00299 {
00300         return d->groupNames;
00301 }
00302 
00303 const QList<QByteArray>&
00304 Set::propertyNamesForGroup(const QByteArray &group) const
00305 {
00306         return d->propertiesOfGroup[group];
00307 }
00308 
00309 void
00310 Set::setGroupDescription(const QByteArray &group, const QString desc)
00311 {
00312         d->groupDescriptions[group] = desc;
00313 }
00314 
00315 QString
00316 Set::groupDescription(const QByteArray &group) const
00317 {
00318         if(d->groupDescriptions.contains(group))
00319                 return d->groupDescriptions[group];
00320         return group;
00321 }
00322 
00323 void
00324 Set::setGroupIcon(const QByteArray &group, const QString& icon)
00325 {
00326         d->groupIcons[group] = icon;
00327 }
00328 
00329 QString
00330 Set::groupIcon(const QByteArray &group) const
00331 {
00332         return d->groupIcons[group];
00333 }
00334 
00335 
00337 
00338 uint
00339 Set::count() const
00340 {
00341         return d->dict.count();
00342 }
00343 
00344 bool
00345 Set::isEmpty() const
00346 {
00347         return d->dict.isEmpty();
00348 }
00349 
00350 bool
00351 Set::isReadOnly() const
00352 {
00353         return d->readOnly;
00354 }
00355 
00356 void
00357 Set::setReadOnly(bool readOnly)
00358 {
00359         d->readOnly = readOnly;
00360 }
00361 
00362 bool
00363 Set::contains(const QByteArray &name) const
00364 {
00365         return d->dict.find(name);
00366 }
00367 
00368 Property&
00369 Set::property(const QByteArray &name) const
00370 {
00371         return d->property(name);
00372 }
00373 
00374 Property&
00375 Set::operator[](const QByteArray &name) const
00376 {
00377         return d->property(name);
00378 }
00379 
00380 const Set&
00381 Set::operator= (const Set &set)
00382 {
00383         if(&set == this)
00384                 return *this;
00385 
00386         clear();
00387 
00388         d->ownProperty = set.d->ownProperty;
00389         d->prevSelection = set.d->prevSelection;
00390         d->groupDescriptions = set.d->groupDescriptions;
00391 
00392         // Copy all properties in the list
00393         for(Property::DictIterator it(set.d->dict); it.current(); ++it) {
00394                 Property *prop = new Property( *it.current() );
00395                 addPropertyInternal(prop, set.d->groupForProperty[ it.current() ], 
00396                         false  );
00397         }
00398 
00399         return *this;
00400 }
00401 
00402 void
00403 Set::changeProperty(const QByteArray &property, const QVariant &value)
00404 {
00405         Property *p = d->dict[property];
00406         if(p)
00407                 p->setValue(value);
00408 }
00409 
00411 
00412 void
00413 Set::debug()
00414 {
00415         //kopropertydbg << "List: typeName='" << m_typeName << "'" << endl;
00416         if(d->dict.isEmpty()) {
00417                 kopropertydbg << "<EMPTY>" << endl;
00418                 return;
00419         }
00420         kopropertydbg << d->dict.count() << " properties:" << endl;
00421 
00422         for(Property::DictIterator it(d->dict); it.current(); ++it)
00423                 it.current()->debug();
00424 }
00425 
00426 QByteArray
00427 Set::prevSelection() const
00428 {
00429         return d->prevSelection;
00430 }
00431 
00432 void
00433 Set::setPrevSelection(const QByteArray &prevSelection)
00434 {
00435         d->prevSelection = prevSelection;
00436 }
00437 
00438 QString
00439 Set::typeName() const
00440 {
00441         return d->typeName;
00442 }
00443 
00445 
00446 Buffer::Buffer()
00447         :Set(false)
00448 {
00449         connect( this, SIGNAL( propertyChanged( KoProperty::Set&, KoProperty::Property& ) ),
00450                  this, SLOT(intersectedChanged( KoProperty::Set&, KoProperty::Property& ) ) );
00451 
00452         connect( this, SIGNAL( propertyReset( KoProperty::Set&, KoProperty::Property& ) ),
00453                  this, SLOT(intersectedReset( KoProperty::Set&, KoProperty::Property& ) ) );
00454 }
00455 
00456 Buffer::Buffer(const Set *set)
00457         :Set(false)
00458 {
00459         connect( this, SIGNAL( propertyChanged( KoProperty::Set&, KoProperty::Property& ) ),
00460                  this, SLOT(intersectedChanged( KoProperty::Set&, KoProperty::Property& ) ) );
00461 
00462         connect( this, SIGNAL( propertyReset( KoProperty::Set&, KoProperty::Property& ) ),
00463                  this, SLOT(intersectedReset( KoProperty::Set&, KoProperty::Property& ) ) );
00464 
00465         initialSet( set );
00466 }
00467 
00468 void Buffer::initialSet(const Set *set)
00469 {
00470         //deep copy of set
00471         for(Property::DictIterator it(set->d->dict); it.current(); ++it) {
00472                 Property *prop = new Property( *it.current() );
00473                 QByteArray group = set->d->groupForProperty[it.current()];
00474                 QString groupDesc = set->d->groupDescriptions[ group ];
00475                 setGroupDescription( group, groupDesc );
00476                 addProperty( prop, group );
00477                 prop->addRelatedProperty( it.current() );
00478         }
00479 }
00480 
00481 void Buffer::intersect(const Set *set)
00482 {
00483         if ( d->dict.isEmpty() )
00484         {
00485                 initialSet( set );
00486                 return;
00487         }
00488 
00489          for(Property::DictIterator it(d->dict); it.current(); ++it) {
00490                 const char* key = it.current()->name();
00491                 if ( Property *property =  set->d->dict[ key ] )
00492                 {
00493                                 blockSignals( true );
00494                                 it.current()->resetValue();
00495                                 it.current()->addRelatedProperty( property );
00496                                 blockSignals( false );
00497                 }
00498                 else
00499                         removeProperty( key );
00500         }
00501 }
00502 
00503 void Buffer::intersectedChanged(KoProperty::Set& set, KoProperty::Property& prop)
00504 {
00505         Q_UNUSED(set);
00506         QByteArray propertyName = prop.name();
00507         if ( !contains( propertyName ) )
00508                 return;
00509 
00510         const QList<Property*> *props = prop.related();
00511         QList<Property*>::ConstIterator it = props->begin();
00512         for ( ; it != props->end(); ++it ) {
00513                 ( *it )->setValue( prop.value(), false );
00514         }
00515 }
00516 
00517 void Buffer::intersectedReset(KoProperty::Set& set, KoProperty::Property& prop)
00518 {
00519         Q_UNUSED(set);
00520         QByteArray propertyName = prop.name();
00521         if ( !contains( propertyName ) )
00522                 return;
00523 
00524         const QList<Property*> *props = prop.related();
00525         QList<Property*>::ConstIterator it = props->begin();
00526         for ( ; it != props->end(); ++it )  {
00527                 ( *it )->setValue( prop.value(), false );
00528         }
00529 }
00530 
00532 
00533 QMap<QByteArray, QVariant> KoProperty::propertyValues(const Set& set)
00534 {
00535         QMap<QByteArray, QVariant> result;
00536         for (Set::Iterator it(set); it.current(); ++it)
00537                 result.insert( it.currentKey(), it.current()->value() );
00538         
00539         return result;
00540 }
00541 
00542 #include "set.moc"

Généré le Wed Nov 22 23:41:07 2006 pour KPlato par  doxygen 1.5.1-p1