00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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
00053 Property::Dict dict;
00054
00055
00056
00057 StringListMap propertiesOfGroup;
00058 QList<QByteArray> groupNames;
00059 QMap<QByteArray, QString> groupDescriptions;
00060 QMap<QByteArray, QString> groupIcons;
00061
00062 QMap<Property*, QByteArray> groupForProperty;
00063
00064 bool ownProperty : 1;
00065 bool readOnly : 1;
00066
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);
00080 kopropertywarn << "Set::property(): PROPERTY \"" << name << "\" NOT FOUND" << endl;
00081 return Set_nonConstNull;
00082 }
00083 };
00084
00085 }
00086
00087 using namespace KoProperty;
00088
00089
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 )
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
00261 if(d->groupForProperty.contains(property) && (d->groupForProperty[property] == group))
00262 return;
00263
00264 if(!d->propertiesOfGroup.contains(group)) {
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
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
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
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
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"