Warning, file /libraries/kproperty/src/KPropertySet.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* This file is part of the KDE project 0002 Copyright (C) 2004 Cedric Pasteur <cedric.pasteur@free.fr> 0003 Copyright (C) 2004 Alexander Dymo <cloudtemple@mskat.net> 0004 Copyright (C) 2004-2017 Jarosław Staniek <staniek@kde.org> 0005 0006 This library is free software; you can redistribute it and/or 0007 modify it under the terms of the GNU Library General Public 0008 License as published by the Free Software Foundation; either 0009 version 2 of the License, or (at your option) any later version. 0010 0011 This library is distributed in the hope that it will be useful, 0012 but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0014 Library General Public License for more details. 0015 0016 You should have received a copy of the GNU Library General Public License 0017 along with this library; see the file COPYING.LIB. If not, write to 0018 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0019 * Boston, MA 02110-1301, USA. 0020 */ 0021 0022 #include "KPropertySet.h" 0023 #include "KPropertySet_p.h" 0024 #include "KProperty_p.h" 0025 0026 #include <QByteArray> 0027 0028 KPropertySetPrivate::KPropertySetPrivate(KPropertySet *set, bool isOwnProperty) 0029 : q(set), m_ownProperty(isOwnProperty) 0030 { 0031 m_groupCaptions.insert("common", QObject::tr("General", "General properties")); 0032 } 0033 0034 KPropertySetPrivate::~KPropertySetPrivate() 0035 { 0036 } 0037 0038 void KPropertySetPrivate::addProperty(KProperty *property, const QByteArray &group/*, bool updateSortingKey*/) 0039 { 0040 if (!property) { 0041 kprWarning() << "property == 0"; 0042 return; 0043 } 0044 if (property->isNull()) { 0045 kprWarning() << "COULD NOT ADD NULL PROPERTY"; 0046 return; 0047 } 0048 const QByteArray realGroup(group.isEmpty() ? "common" : group); 0049 KProperty *p = this->property(property->name()); 0050 if (p) { 0051 addRelatedProperty(p, property); 0052 } 0053 else { 0054 m_list.append(property); 0055 m_hash.insert(property->name().toLower(), property); 0056 if (property->isVisible()) { 0057 m_visiblePropertiesCount++; 0058 } 0059 addToGroup(realGroup, property); 0060 } 0061 0062 property->d->addSet(q); 0063 #if 0 0064 if (updateSortingKey) 0065 property->setSortingKey(count()); 0066 #endif 0067 } 0068 0069 void KPropertySetPrivate::removeProperty(KProperty *property) 0070 { 0071 if (!property) 0072 return; 0073 0074 if (!m_list.removeOne(property)) { 0075 kprDebug() << "The property set does not contain property" << property; 0076 return; 0077 } 0078 KProperty *p = m_hash.take(property->name().toLower()); 0079 if (p) { 0080 removeFromGroup(p); 0081 if (p->isVisible()) { 0082 m_visiblePropertiesCount--; 0083 } 0084 if (m_ownProperty) { 0085 emit q->aboutToDeleteProperty(*q, *p); 0086 delete p; 0087 } 0088 } 0089 } 0090 0091 void KPropertySetPrivate::clear() 0092 { 0093 if (m_informAboutClearing) { 0094 *m_informAboutClearing = true; 0095 } 0096 m_informAboutClearing = nullptr; 0097 emit q->aboutToBeCleared(); 0098 m_visiblePropertiesCount = 0; 0099 qDeleteAll(m_propertiesOfGroup); 0100 m_propertiesOfGroup.clear(); 0101 m_groupNames.clear(); 0102 m_groupForProperties.clear(); 0103 m_groupCaptions.clear(); 0104 m_groupIconNames.clear(); 0105 qDeleteAll(m_list); 0106 m_list.clear(); 0107 m_hash.clear(); 0108 } 0109 0110 void KPropertySetPrivate::copyAttributesFrom(const KPropertySetPrivate &other) 0111 { 0112 KPropertySet *origSet = q; 0113 *this = other; 0114 q = origSet; 0115 // do not copy too deeply 0116 m_list.clear(); 0117 m_hash.clear(); 0118 m_propertiesOfGroup.clear(); 0119 m_groupForProperties.clear(); 0120 m_visiblePropertiesCount = 0; 0121 m_informAboutClearing = nullptr; 0122 } 0123 0124 void KPropertySetPrivate::copyPropertiesFrom( 0125 const QList<KProperty*>::ConstIterator& constBegin, 0126 const QList<KProperty*>::ConstIterator& constEnd, const KPropertySet & set) 0127 { 0128 for (QList<KProperty*>::ConstIterator it(constBegin); it!=constEnd; ++it) { 0129 KProperty *prop = new KProperty(*(*it)); 0130 addProperty(prop, set.d->groupForProperty( *it ) 0131 #if 0 0132 , 0133 false /* don't updateSortingKey, because the key is already 0134 set in KProperty copy ctor.*/ 0135 #endif 0136 ); 0137 } 0138 } 0139 0140 void KPropertySetPrivate::addToGroup(const QByteArray &group, KProperty *property) 0141 { 0142 if (!property || group.isEmpty()) { 0143 return; 0144 } 0145 //do not add the same property to the group twice 0146 const QByteArray groupLower(group.toLower()); 0147 if (groupForProperty(property) == groupLower) { 0148 kprWarning() << "Group" << group << "already contains property" << property->name(); 0149 return; 0150 } 0151 QList<QByteArray>* propertiesOfGroup = m_propertiesOfGroup.value(groupLower); 0152 if (!propertiesOfGroup) { 0153 propertiesOfGroup = new QList<QByteArray>(); 0154 m_propertiesOfGroup.insert(groupLower, propertiesOfGroup); 0155 m_groupNames.append(groupLower); 0156 } 0157 propertiesOfGroup->append(property->name()); 0158 addPropertyToGroup(property, groupLower); 0159 } 0160 0161 void KPropertySetPrivate::removeFromGroup(KProperty *property) 0162 { 0163 if (!property) { 0164 return; 0165 } 0166 const QByteArray group(groupForProperty(property)); 0167 if (group.isEmpty()) { 0168 return; 0169 } 0170 QList<QByteArray>* propertiesOfGroup = m_propertiesOfGroup.value(group); 0171 if (propertiesOfGroup) { 0172 propertiesOfGroup->removeAt(propertiesOfGroup->indexOf(property->name())); 0173 if (propertiesOfGroup->isEmpty()) { 0174 //remove group as well 0175 m_propertiesOfGroup.take(group); 0176 delete propertiesOfGroup; 0177 const int i = m_groupNames.indexOf(group); 0178 if (i != -1) { 0179 m_groupNames.removeAt(i); 0180 } 0181 } 0182 } 0183 removePropertyFromGroup(property); 0184 } 0185 0186 bool KPropertySetPrivate::hasGroups() const 0187 { 0188 return m_groupNames.count() > 1 || (m_groupNames.count() == 1 && m_groupNames.first() != "common"); 0189 } 0190 0191 void KPropertySetPrivate::informAboutClearing(bool* cleared) 0192 { 0193 Q_ASSERT(cleared); 0194 *cleared = false; 0195 m_informAboutClearing = cleared; 0196 } 0197 0198 void KPropertySetPrivate::addRelatedProperty(KProperty *p1, KProperty *p2) const 0199 { 0200 p1->d->addRelatedProperty(p2); 0201 } 0202 0203 int KPropertySetPrivate::indexOfProperty(const KProperty *property) const 0204 { 0205 KProperty *parentProperty = property->parent(); 0206 if (parentProperty) { 0207 const QList<KProperty*>* children = parentProperty->children(); 0208 Q_ASSERT(children); 0209 const int index = children->indexOf(parentProperty); 0210 Q_ASSERT(index != -1); 0211 return index; 0212 } 0213 return indexOfPropertyInGroup(property); 0214 } 0215 0216 int KPropertySetPrivate::indexOfPropertyInGroup(const KProperty *property) const 0217 { 0218 const QByteArray group(m_groupForProperties.value(const_cast<KProperty *>(property))); 0219 QList<QByteArray>* propertiesOfGroup = m_propertiesOfGroup.value(group); 0220 if (!propertiesOfGroup) { 0221 return -1; 0222 } 0223 return propertiesOfGroup->indexOf(property->name()); 0224 } 0225 0226 QString KPropertySetPrivate::groupCaption(const QByteArray &group) const 0227 { 0228 const QString result(m_groupCaptions.value(group.toLower())); 0229 if (!result.isEmpty()) 0230 return result; 0231 return QLatin1String(group); 0232 } 0233 0234 ////////////////////////////////////////////// 0235 0236 KPropertySelector::KPropertySelector() 0237 { 0238 } 0239 0240 KPropertySelector::~KPropertySelector() 0241 { 0242 } 0243 0244 ////////////////////////////////////////////// 0245 0246 typedef QPair<KProperty*, QString> Iterator_PropertyAndString; 0247 0248 static inline bool Iterator_propertyAndStringLessThan( 0249 const Iterator_PropertyAndString &n1, const Iterator_PropertyAndString &n2) 0250 { 0251 return QString::compare(n1.second, n2.second, Qt::CaseInsensitive) < 0; 0252 } 0253 0254 ////////////////////////////////////////////// 0255 0256 class Q_DECL_HIDDEN KPropertySetIterator::Private 0257 { 0258 public: 0259 explicit Private(KPropertySetIterator *iter) : q(iter) 0260 { 0261 } 0262 Private(KPropertySetIterator *iter, const Private &other) 0263 : q(iter) 0264 { 0265 copy(other); 0266 } 0267 ~Private() 0268 { 0269 delete selector; 0270 } 0271 0272 #define KPropertySetIteratorPrivateArgs(o) std::tie(o.set, o.iterator, o.end, o.selector, o.order, o.sorted) 0273 void copy(const Private &other) { 0274 KPropertySetIteratorPrivateArgs((*this)) = KPropertySetIteratorPrivateArgs(other); 0275 } 0276 bool operator==(const Private &other) const { 0277 return KPropertySetIteratorPrivateArgs((*this)) == KPropertySetIteratorPrivateArgs(other); 0278 } 0279 0280 void skipNotAcceptable() 0281 { 0282 if (!selector) 0283 return; 0284 //kprDebug() << "FROM:" << *current(); 0285 if (q->current() && !(*selector)( *q->current() )) { 0286 // skip first items that not are acceptable by the selector 0287 ++(*q); 0288 } 0289 //kprDebug() << "TO:" << *current(); 0290 } 0291 0292 const KPropertySet *set; 0293 QList<KProperty*>::ConstIterator iterator; 0294 QList<KProperty*>::ConstIterator end; 0295 KPropertySelector *selector; 0296 KPropertySetIterator::Order order; 0297 QList<KProperty*> sorted; //!< for sorted order 0298 0299 private: 0300 KPropertySetIterator * const q; 0301 }; 0302 0303 KPropertySetIterator::KPropertySetIterator(const KPropertySet &set) 0304 : d(new Private(this)) 0305 { 0306 d->set = &set; 0307 d->iterator = KPropertySetPrivate::d(&set)->listConstIterator(); 0308 d->end = KPropertySetPrivate::d(&set)->listConstEnd(); 0309 d->selector = nullptr; 0310 d->order = KPropertySetIterator::Order::Insertion; 0311 } 0312 0313 KPropertySetIterator::KPropertySetIterator(const KPropertySet &set, 0314 const KPropertySelector &selector) 0315 : d(new Private(this)) 0316 { 0317 d->set = &set; 0318 d->iterator = KPropertySetPrivate::d(&set)->listConstIterator(); 0319 d->end = KPropertySetPrivate::d(&set)->listConstEnd(); 0320 d->selector = selector.clone(); 0321 d->order = KPropertySetIterator::Order::Insertion; 0322 d->skipNotAcceptable(); 0323 } 0324 0325 KPropertySetIterator::KPropertySetIterator(const KPropertySetIterator &set) 0326 : d(new Private(this, *set.d)) 0327 { 0328 } 0329 0330 KPropertySetIterator& KPropertySetIterator::operator=(const KPropertySetIterator &other) 0331 { 0332 if (this != &other) { 0333 d->copy(*other.d); 0334 } 0335 return *this; 0336 } 0337 0338 bool KPropertySetIterator::operator==(const KPropertySetIterator &other) const 0339 { 0340 return *d == *other.d; 0341 } 0342 0343 KPropertySetIterator::~KPropertySetIterator() 0344 { 0345 delete d; 0346 } 0347 0348 void KPropertySetIterator::setOrder(KPropertySetIterator::Order order) 0349 { 0350 if (d->order == order) 0351 return; 0352 d->order = order; 0353 switch (d->order) { 0354 case KPropertySetIterator::Order::Alphabetical: 0355 case KPropertySetIterator::Order::AlphabeticalByName: 0356 { 0357 QList<Iterator_PropertyAndString> propertiesAndStrings; 0358 d->iterator = KPropertySetPrivate::d(d->set)->listConstIterator(); 0359 d->end = KPropertySetPrivate::d(d->set)->listConstEnd(); 0360 for (; d->iterator!=d->end; ++d->iterator) { 0361 KProperty *prop = *d->iterator; 0362 QString captionOrName; 0363 if (d->order == KPropertySetIterator::Order::Alphabetical) { 0364 captionOrName = prop->caption(); 0365 } 0366 if (captionOrName.isEmpty()) { 0367 captionOrName = QLatin1String(prop->name()); 0368 } 0369 propertiesAndStrings.append( qMakePair(prop, captionOrName) ); 0370 } 0371 std::sort(propertiesAndStrings.begin(), propertiesAndStrings.end(), 0372 Iterator_propertyAndStringLessThan); 0373 d->sorted.clear(); 0374 foreach (const Iterator_PropertyAndString& propertyAndString, propertiesAndStrings) { 0375 d->sorted.append(propertyAndString.first); 0376 } 0377 // restart the iterator 0378 d->iterator = d->sorted.constBegin(); 0379 d->end = d->sorted.constEnd(); 0380 break; 0381 } 0382 default: 0383 d->sorted.clear(); 0384 // restart the iterator 0385 d->iterator = KPropertySetPrivate::d(d->set)->listConstIterator(); 0386 d->end = KPropertySetPrivate::d(d->set)->listConstEnd(); 0387 } 0388 d->skipNotAcceptable(); 0389 } 0390 0391 KPropertySetIterator::Order KPropertySetIterator::order() const 0392 { 0393 return d->order; 0394 } 0395 0396 KProperty* KPropertySetIterator::current() const 0397 { 0398 return d->iterator == d->end ? nullptr : *d->iterator; 0399 } 0400 0401 void KPropertySetIterator::operator ++() 0402 { 0403 while (true) { 0404 ++d->iterator; 0405 if (!d->selector) 0406 return; 0407 // selector exists 0408 if (!current()) // end encountered 0409 return; 0410 if ((*d->selector)( *current() )) 0411 return; 0412 } 0413 } 0414 0415 ////////////////////////////////////////////// 0416 0417 KPropertySet::KPropertySet(QObject *parent) 0418 : QObject(parent) 0419 , d(new KPropertySetPrivate(this, true)) 0420 { 0421 } 0422 0423 0424 KPropertySet::KPropertySet(const KPropertySet &set) 0425 : QObject(nullptr /* implicit sharing the parent is dangerous */) 0426 , d(new KPropertySetPrivate(this, true)) 0427 { 0428 setObjectName(set.objectName()); 0429 *this = set; 0430 } 0431 0432 KPropertySet::KPropertySet(bool propertyOwner) 0433 : QObject(nullptr) 0434 , d(new KPropertySetPrivate(this, propertyOwner)) 0435 { 0436 } 0437 0438 KPropertySet::~KPropertySet() 0439 { 0440 emit aboutToBeCleared(); 0441 emit aboutToBeDeleted(); 0442 clear(); 0443 delete d; 0444 } 0445 0446 ///////////////////////////////////////////////////// 0447 0448 void 0449 KPropertySet::addProperty(KProperty *property, const QByteArray &group) 0450 { 0451 d->addProperty(property, group); 0452 } 0453 0454 void 0455 KPropertySet::removeProperty(KProperty *property) 0456 { 0457 d->removeProperty(property); 0458 } 0459 0460 void 0461 KPropertySet::removeProperty(const QByteArray &name) 0462 { 0463 KProperty *p = d->property(name); 0464 removeProperty(p); 0465 } 0466 0467 void 0468 KPropertySet::clear() 0469 { 0470 d->clear(); 0471 } 0472 0473 ///////////////////////////////////////////////////// 0474 0475 QByteArray KPropertySet::groupNameForProperty(const QByteArray &propertyName) const 0476 { 0477 const KProperty *property = d->property(propertyName); 0478 return property ? groupNameForProperty(*property) : QByteArray(); 0479 } 0480 0481 QByteArray KPropertySet::groupNameForProperty(const KProperty &property) const 0482 { 0483 return d->groupForProperty(&property); 0484 } 0485 0486 QList<QByteArray> KPropertySet::groupNames() const 0487 { 0488 return d->groupNames(); 0489 } 0490 0491 QList<QByteArray> KPropertySet::propertyNamesForGroup(const QByteArray &group) const 0492 { 0493 QList<QByteArray>* propertiesOfGroup = d->propertyNamesForGroup(group); 0494 return propertiesOfGroup ? *propertiesOfGroup : QList<QByteArray>(); 0495 } 0496 0497 void KPropertySet::setGroupCaption(const QByteArray &group, const QString &caption) 0498 { 0499 d->setGroupCaption(group, caption); 0500 } 0501 0502 QString KPropertySet::groupCaption(const QByteArray &group) const 0503 { 0504 return d->groupCaption(group); 0505 } 0506 0507 void KPropertySet::setGroupIconName(const QByteArray &group, const QString& iconName) 0508 { 0509 d->setGroupIconName(group, iconName); 0510 } 0511 0512 QString KPropertySet::groupIconName(const QByteArray &group) const 0513 { 0514 return d->groupIconName(group); 0515 } 0516 0517 ///////////////////////////////////////////////////// 0518 0519 int KPropertySet::count() const 0520 { 0521 return d->count(); 0522 } 0523 0524 int KPropertySet::count(const KPropertySelector& selector) const 0525 { 0526 int result = 0; 0527 for (KPropertySetIterator it(*this, selector); it.current(); ++it, result++) 0528 ; 0529 return result; 0530 } 0531 0532 bool 0533 KPropertySet::isEmpty() const 0534 { 0535 return d->isEmpty(); 0536 } 0537 0538 bool KPropertySet::hasVisibleProperties() const 0539 { 0540 return d->visiblePropertiesCount() > 0; 0541 } 0542 0543 bool KPropertySet::hasProperties(const KPropertySelector& selector) const 0544 { 0545 KPropertySetIterator it(*this, selector); 0546 return it.current(); 0547 } 0548 0549 bool 0550 KPropertySet::isReadOnly() const 0551 { 0552 return d->readOnly; 0553 } 0554 0555 void 0556 KPropertySet::setReadOnly(bool readOnly) 0557 { 0558 if (d->readOnly != readOnly) { 0559 d->readOnly = readOnly; 0560 emit readOnlyFlagChanged(); 0561 } 0562 } 0563 0564 bool 0565 KPropertySet::contains(const QByteArray &name) const 0566 { 0567 return d->property(name); 0568 } 0569 0570 KProperty& 0571 KPropertySet::property(const QByteArray &name) const 0572 { 0573 return d->propertyOrNull(name); 0574 } 0575 0576 void KPropertySet::changePropertyIfExists(const QByteArray &property, const QVariant &value) 0577 { 0578 if (contains(property)) { 0579 changeProperty(property, value); 0580 } 0581 } 0582 0583 KProperty& 0584 KPropertySet::operator[](const QByteArray &name) const 0585 { 0586 return d->propertyOrNull(name); 0587 } 0588 0589 KPropertySet& 0590 KPropertySet::operator= (const KPropertySet & set) 0591 { 0592 if (&set == this) 0593 return *this; 0594 0595 clear(); 0596 d->copyAttributesFrom(*set.d); 0597 d->copyPropertiesFrom(set.d->listConstIterator(), set.d->listConstEnd(), set); 0598 return *this; 0599 } 0600 0601 QVariant KPropertySet::propertyValue(const QByteArray &name, const QVariant& defaultValue) const 0602 { 0603 const KProperty *p = d->property(name); 0604 return p ? p->value() : defaultValue; 0605 } 0606 0607 void 0608 KPropertySet::changeProperty(const QByteArray &property, const QVariant &value) 0609 { 0610 KProperty *p = d->property(property); 0611 if (p) 0612 p->setValue(value); 0613 } 0614 0615 void KPropertySet::debug() const 0616 { 0617 kprDebug() << *this; 0618 } 0619 0620 KPROPERTYCORE_EXPORT QDebug operator<<(QDebug dbg, const KPropertySet &set) 0621 { 0622 dbg.nospace() << "KPropertySet("; 0623 if (set.isEmpty()) { 0624 dbg.space() << "<EMPTY>)"; 0625 return dbg.space(); 0626 } 0627 dbg.nospace() << " PROPERTIES(" << set.count() << "):\n"; 0628 0629 KPropertySetIterator it(set); 0630 it.setOrder(KPropertySetIterator::Order::AlphabeticalByName); 0631 bool first = true; 0632 for ( ; it.current(); ++it) { 0633 if (first) { 0634 first = false; 0635 } 0636 else { 0637 dbg.nospace() << "\n"; 0638 } 0639 dbg.nospace() << *it.current(); 0640 } 0641 dbg.nospace() << "\n)"; 0642 return dbg.space(); 0643 } 0644 0645 QByteArray KPropertySet::previousSelection() const 0646 { 0647 return d->previousSelection(); 0648 } 0649 0650 void KPropertySet::setPreviousSelection(const QByteArray &prevSelection) 0651 { 0652 d->setPreviousSelection(prevSelection); 0653 } 0654 0655 QMap<QByteArray, QVariant> KPropertySet::propertyValues() const 0656 { 0657 QMap<QByteArray, QVariant> result; 0658 for (KPropertySetIterator it(*this); it.current(); ++it) { 0659 result.insert(it.current()->name(), it.current()->value()); 0660 } 0661 return result; 0662 } 0663 0664 void KPropertySet::clearModifiedFlags() 0665 { 0666 for (KPropertySetIterator it(*this); it.current(); ++it) { 0667 it.current()->clearModifiedFlag(); 0668 } 0669 } 0670 0671 bool KPropertySet::isModified() const 0672 { 0673 for (KPropertySetIterator it(*this); it.current(); ++it) { 0674 if (it.current()->isModified()) { 0675 return true; 0676 } 0677 } 0678 return false; 0679 }