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 <qasciidict.h>
00028
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
00053 Property::Dict dict;
00054
00055
00056
00057 StringListMap propertiesOfGroup;
00058 QValueList<QCString> groupNames;
00059 QMap<QCString, QString> groupDescriptions;
00060 QMap<QCString, QString> groupIcons;
00061
00062 QMap<Property*, QCString> groupForProperty;
00063
00064 bool ownProperty : 1;
00065 bool readOnly : 1;
00066
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);
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 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 , 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
00258 if(d->groupForProperty.contains(property) && (d->groupForProperty[property] == group))
00259 return;
00260
00261 if(!d->propertiesOfGroup.contains(group)) {
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
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
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
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
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"