KProperty

KPropertySet.cpp
1 /* This file is part of the KDE project
2  Copyright (C) 2004 Cedric Pasteur <[email protected]>
3  Copyright (C) 2004 Alexander Dymo <[email protected]>
4  Copyright (C) 2004-2017 Jarosław Staniek <[email protected]>
5 
6  This library is free software; you can redistribute it and/or
7  modify it under the terms of the GNU Library General Public
8  License as published by the Free Software Foundation; either
9  version 2 of the License, or (at your option) any later version.
10 
11  This library is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  Library General Public License for more details.
15 
16  You should have received a copy of the GNU Library General Public License
17  along with this library; see the file COPYING.LIB. If not, write to
18  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20 */
21 
22 #include "KPropertySet.h"
23 #include "KPropertySet_p.h"
24 #include "KProperty_p.h"
25 
26 #include <QByteArray>
27 
28 KPropertySetPrivate::KPropertySetPrivate(KPropertySet *set, bool isOwnProperty)
29  : q(set), m_ownProperty(isOwnProperty)
30 {
31  m_groupCaptions.insert("common", QObject::tr("General", "General properties"));
32 }
33 
34 KPropertySetPrivate::~KPropertySetPrivate()
35 {
36 }
37 
38 void KPropertySetPrivate::addProperty(KProperty *property, const QByteArray &group/*, bool updateSortingKey*/)
39 {
40  if (!property) {
41  kprWarning() << "property == 0";
42  return;
43  }
44  if (property->isNull()) {
45  kprWarning() << "COULD NOT ADD NULL PROPERTY";
46  return;
47  }
48  const QByteArray realGroup(group.isEmpty() ? "common" : group);
49  KProperty *p = this->property(property->name());
50  if (p) {
51  addRelatedProperty(p, property);
52  }
53  else {
54  m_list.append(property);
55  m_hash.insert(property->name().toLower(), property);
56  if (property->isVisible()) {
57  m_visiblePropertiesCount++;
58  }
59  addToGroup(realGroup, property);
60  }
61 
62  property->d->addSet(q);
63 #if 0
64  if (updateSortingKey)
65  property->setSortingKey(count());
66 #endif
67 }
68 
69 void KPropertySetPrivate::removeProperty(KProperty *property)
70 {
71  if (!property)
72  return;
73 
74  if (!m_list.removeOne(property)) {
75  kprDebug() << "The property set does not contain property" << property;
76  return;
77  }
78  KProperty *p = m_hash.take(property->name().toLower());
79  if (p) {
80  removeFromGroup(p);
81  if (p->isVisible()) {
82  m_visiblePropertiesCount--;
83  }
84  if (m_ownProperty) {
85  emit q->aboutToDeleteProperty(*q, *p);
86  delete p;
87  }
88  }
89 }
90 
91 void KPropertySetPrivate::clear()
92 {
93  if (m_informAboutClearing) {
94  *m_informAboutClearing = true;
95  }
96  m_informAboutClearing = nullptr;
97  emit q->aboutToBeCleared();
98  m_visiblePropertiesCount = 0;
99  qDeleteAll(m_propertiesOfGroup);
100  m_propertiesOfGroup.clear();
101  m_groupNames.clear();
102  m_groupForProperties.clear();
103  m_groupCaptions.clear();
104  m_groupIconNames.clear();
105  qDeleteAll(m_list);
106  m_list.clear();
107  m_hash.clear();
108 }
109 
110 void KPropertySetPrivate::copyAttributesFrom(const KPropertySetPrivate &other)
111 {
112  KPropertySet *origSet = q;
113  *this = other;
114  q = origSet;
115  // do not copy too deeply
116  m_list.clear();
117  m_hash.clear();
118  m_propertiesOfGroup.clear();
119  m_groupForProperties.clear();
120  m_visiblePropertiesCount = 0;
121  m_informAboutClearing = nullptr;
122 }
123 
124 void KPropertySetPrivate::copyPropertiesFrom(
125  const QList<KProperty*>::ConstIterator& constBegin,
126  const QList<KProperty*>::ConstIterator& constEnd, const KPropertySet & set)
127 {
128  for (QList<KProperty*>::ConstIterator it(constBegin); it!=constEnd; ++it) {
129  KProperty *prop = new KProperty(*(*it));
130  addProperty(prop, set.d->groupForProperty( *it )
131 #if 0
132  ,
133  false /* don't updateSortingKey, because the key is already
134  set in KProperty copy ctor.*/
135 #endif
136  );
137  }
138 }
139 
140 void KPropertySetPrivate::addToGroup(const QByteArray &group, KProperty *property)
141 {
142  if (!property || group.isEmpty()) {
143  return;
144  }
145  //do not add the same property to the group twice
146  const QByteArray groupLower(group.toLower());
147  if (groupForProperty(property) == groupLower) {
148  kprWarning() << "Group" << group << "already contains property" << property->name();
149  return;
150  }
151  QList<QByteArray>* propertiesOfGroup = m_propertiesOfGroup.value(groupLower);
152  if (!propertiesOfGroup) {
153  propertiesOfGroup = new QList<QByteArray>();
154  m_propertiesOfGroup.insert(groupLower, propertiesOfGroup);
155  m_groupNames.append(groupLower);
156  }
157  propertiesOfGroup->append(property->name());
158  addPropertyToGroup(property, groupLower);
159 }
160 
161 void KPropertySetPrivate::removeFromGroup(KProperty *property)
162 {
163  if (!property) {
164  return;
165  }
166  const QByteArray group(groupForProperty(property));
167  if (group.isEmpty()) {
168  return;
169  }
170  QList<QByteArray>* propertiesOfGroup = m_propertiesOfGroup.value(group);
171  if (propertiesOfGroup) {
172  propertiesOfGroup->removeAt(propertiesOfGroup->indexOf(property->name()));
173  if (propertiesOfGroup->isEmpty()) {
174  //remove group as well
175  m_propertiesOfGroup.take(group);
176  delete propertiesOfGroup;
177  const int i = m_groupNames.indexOf(group);
178  if (i != -1) {
179  m_groupNames.removeAt(i);
180  }
181  }
182  }
183  removePropertyFromGroup(property);
184 }
185 
186 bool KPropertySetPrivate::hasGroups() const
187 {
188  return m_groupNames.count() > 1 || (m_groupNames.count() == 1 && m_groupNames.first() != "common");
189 }
190 
191 void KPropertySetPrivate::informAboutClearing(bool* cleared)
192 {
193  Q_ASSERT(cleared);
194  *cleared = false;
195  m_informAboutClearing = cleared;
196 }
197 
198 void KPropertySetPrivate::addRelatedProperty(KProperty *p1, KProperty *p2) const
199 {
200  p1->d->addRelatedProperty(p2);
201 }
202 
203 int KPropertySetPrivate::indexOfProperty(const KProperty *property) const
204 {
205  KProperty *parentProperty = property->parent();
206  if (parentProperty) {
207  const QList<KProperty*>* children = parentProperty->children();
208  Q_ASSERT(children);
209  const int index = children->indexOf(parentProperty);
210  Q_ASSERT(index != -1);
211  return index;
212  }
213  return indexOfPropertyInGroup(property);
214 }
215 
216 int KPropertySetPrivate::indexOfPropertyInGroup(const KProperty *property) const
217 {
218  const QByteArray group(m_groupForProperties.value(const_cast<KProperty *>(property)));
219  QList<QByteArray>* propertiesOfGroup = m_propertiesOfGroup.value(group);
220  if (!propertiesOfGroup) {
221  return -1;
222  }
223  return propertiesOfGroup->indexOf(property->name());
224 }
225 
226 QString KPropertySetPrivate::groupCaption(const QByteArray &group) const
227 {
228  const QString result(m_groupCaptions.value(group.toLower()));
229  if (!result.isEmpty())
230  return result;
231  return QLatin1String(group);
232 }
233 
235 
236 KPropertySelector::KPropertySelector()
237 {
238 }
239 
240 KPropertySelector::~KPropertySelector()
241 {
242 }
243 
245 
247 
248 static inline bool Iterator_propertyAndStringLessThan(
249  const Iterator_PropertyAndString &n1, const Iterator_PropertyAndString &n2)
250 {
251  return QString::compare(n1.second, n2.second, Qt::CaseInsensitive) < 0;
252 }
253 
255 
256 class Q_DECL_HIDDEN KPropertySetIterator::Private
257 {
258 public:
259  explicit Private(KPropertySetIterator *iter) : q(iter)
260  {
261  }
262  Private(KPropertySetIterator *iter, const Private &other)
263  : q(iter)
264  {
265  copy(other);
266  }
267  ~Private()
268  {
269  delete selector;
270  }
271 
272 #define KPropertySetIteratorPrivateArgs(o) std::tie(o.set, o.iterator, o.end, o.selector, o.order, o.sorted)
273  void copy(const Private &other) {
274  KPropertySetIteratorPrivateArgs((*this)) = KPropertySetIteratorPrivateArgs(other);
275  }
276  bool operator==(const Private &other) const {
277  return KPropertySetIteratorPrivateArgs((*this)) == KPropertySetIteratorPrivateArgs(other);
278  }
279 
280  void skipNotAcceptable()
281  {
282  if (!selector)
283  return;
284  //kprDebug() << "FROM:" << *current();
285  if (q->current() && !(*selector)( *q->current() )) {
286  // skip first items that not are acceptable by the selector
287  ++(*q);
288  }
289  //kprDebug() << "TO:" << *current();
290  }
291 
292  const KPropertySet *set;
295  KPropertySelector *selector;
297  QList<KProperty*> sorted;
298 
299 private:
300  KPropertySetIterator * const q;
301 };
302 
304  : d(new Private(this))
305 {
306  d->set = &set;
307  d->iterator = KPropertySetPrivate::d(&set)->listConstIterator();
308  d->end = KPropertySetPrivate::d(&set)->listConstEnd();
309  d->selector = nullptr;
311 }
312 
314  const KPropertySelector &selector)
315  : d(new Private(this))
316 {
317  d->set = &set;
318  d->iterator = KPropertySetPrivate::d(&set)->listConstIterator();
319  d->end = KPropertySetPrivate::d(&set)->listConstEnd();
320  d->selector = selector.clone();
322  d->skipNotAcceptable();
323 }
324 
326  : d(new Private(this, *set.d))
327 {
328 }
329 
331 {
332  if (this != &other) {
333  d->copy(*other.d);
334  }
335  return *this;
336 }
337 
339 {
340  return *d == *other.d;
341 }
342 
343 KPropertySetIterator::~KPropertySetIterator()
344 {
345  delete d;
346 }
347 
349 {
350  if (d->order == order)
351  return;
352  d->order = order;
353  switch (d->order) {
356  {
357  QList<Iterator_PropertyAndString> propertiesAndStrings;
358  d->iterator = KPropertySetPrivate::d(d->set)->listConstIterator();
359  d->end = KPropertySetPrivate::d(d->set)->listConstEnd();
360  for (; d->iterator!=d->end; ++d->iterator) {
361  KProperty *prop = *d->iterator;
362  QString captionOrName;
364  captionOrName = prop->caption();
365  }
366  if (captionOrName.isEmpty()) {
367  captionOrName = QLatin1String(prop->name());
368  }
369  propertiesAndStrings.append( qMakePair(prop, captionOrName) );
370  }
371  qSort(propertiesAndStrings.begin(), propertiesAndStrings.end(),
372  Iterator_propertyAndStringLessThan);
373  d->sorted.clear();
374  foreach (const Iterator_PropertyAndString& propertyAndString, propertiesAndStrings) {
375  d->sorted.append(propertyAndString.first);
376  }
377  // restart the iterator
378  d->iterator = d->sorted.constBegin();
379  d->end = d->sorted.constEnd();
380  break;
381  }
382  default:
383  d->sorted.clear();
384  // restart the iterator
385  d->iterator = KPropertySetPrivate::d(d->set)->listConstIterator();
386  d->end = KPropertySetPrivate::d(d->set)->listConstEnd();
387  }
388  d->skipNotAcceptable();
389 }
390 
392 {
393  return d->order;
394 }
395 
396 KProperty* KPropertySetIterator::current() const
397 {
398  return d->iterator == d->end ? nullptr : *d->iterator;
399 }
400 
401 void KPropertySetIterator::operator ++()
402 {
403  while (true) {
404  ++d->iterator;
405  if (!d->selector)
406  return;
407  // selector exists
408  if (!current()) // end encountered
409  return;
410  if ((*d->selector)( *current() ))
411  return;
412  }
413 }
414 
416 
418  : QObject(parent)
419  , d(new KPropertySetPrivate(this, true))
420 {
421 }
422 
423 
425  : QObject(nullptr /* implicit sharing the parent is dangerous */)
426  , d(new KPropertySetPrivate(this, true))
427 {
428  setObjectName(set.objectName());
429  *this = set;
430 }
431 
432 KPropertySet::KPropertySet(bool propertyOwner)
433  : QObject(nullptr)
434  , d(new KPropertySetPrivate(this, propertyOwner))
435 {
436 }
437 
438 KPropertySet::~KPropertySet()
439 {
440  emit aboutToBeCleared();
441  emit aboutToBeDeleted();
442  clear();
443  delete d;
444 }
445 
447 
448 void
450 {
451  d->addProperty(property, group);
452 }
453 
454 void
456 {
457  d->removeProperty(property);
458 }
459 
460 void
462 {
463  KProperty *p = d->property(name);
464  removeProperty(p);
465 }
466 
467 void
469 {
470  d->clear();
471 }
472 
474 
476 {
477  const KProperty *property = d->property(propertyName);
478  return property ? groupNameForProperty(*property) : QByteArray();
479 }
480 
482 {
483  return d->groupForProperty(&property);
484 }
485 
487 {
488  return d->groupNames();
489 }
490 
492 {
493  QList<QByteArray>* propertiesOfGroup = d->propertyNamesForGroup(group);
494  return propertiesOfGroup ? *propertiesOfGroup : QList<QByteArray>();
495 }
496 
497 void KPropertySet::setGroupCaption(const QByteArray &group, const QString &caption)
498 {
499  d->setGroupCaption(group, caption);
500 }
501 
503 {
504  return d->groupCaption(group);
505 }
506 
507 void KPropertySet::setGroupIconName(const QByteArray &group, const QString& iconName)
508 {
509  d->setGroupIconName(group, iconName);
510 }
511 
513 {
514  return d->groupIconName(group);
515 }
516 
518 
520 {
521  return d->count();
522 }
523 
524 int KPropertySet::count(const KPropertySelector& selector) const
525 {
526  int result = 0;
527  for (KPropertySetIterator it(*this, selector); it.current(); ++it, result++)
528  ;
529  return result;
530 }
531 
532 bool
534 {
535  return d->isEmpty();
536 }
537 
539 {
540  return d->visiblePropertiesCount() > 0;
541 }
542 
544 {
545  KPropertySetIterator it(*this, selector);
546  return it.current();
547 }
548 
549 bool
551 {
552  return d->readOnly;
553 }
554 
555 void
557 {
558  if (d->readOnly != readOnly) {
559  d->readOnly = readOnly;
560  emit readOnlyFlagChanged();
561  }
562 }
563 
564 bool
566 {
567  return d->property(name);
568 }
569 
570 KProperty&
572 {
573  return d->propertyOrNull(name);
574 }
575 
576 void KPropertySet::changePropertyIfExists(const QByteArray &property, const QVariant &value)
577 {
578  if (contains(property)) {
579  changeProperty(property, value);
580  }
581 }
582 
583 KProperty&
585 {
586  return d->propertyOrNull(name);
587 }
588 
591 {
592  if (&set == this)
593  return *this;
594 
595  clear();
596  d->copyAttributesFrom(*set.d);
597  d->copyPropertiesFrom(set.d->listConstIterator(), set.d->listConstEnd(), set);
598  return *this;
599 }
600 
601 QVariant KPropertySet::propertyValue(const QByteArray &name, const QVariant& defaultValue) const
602 {
603  const KProperty *p = d->property(name);
604  return p ? p->value() : defaultValue;
605 }
606 
607 void
608 KPropertySet::changeProperty(const QByteArray &property, const QVariant &value)
609 {
610  KProperty *p = d->property(property);
611  if (p)
612  p->setValue(value);
613 }
614 
616 {
617  kprDebug() << *this;
618 }
619 
620 KPROPERTYCORE_EXPORT QDebug operator<<(QDebug dbg, const KPropertySet &set)
621 {
622  dbg.nospace() << "KPropertySet(";
623  if (set.isEmpty()) {
624  dbg.space() << "<EMPTY>)";
625  return dbg.space();
626  }
627  dbg.nospace() << " PROPERTIES(" << set.count() << "):\n";
628 
629  KPropertySetIterator it(set);
631  bool first = true;
632  for ( ; it.current(); ++it) {
633  if (first) {
634  first = false;
635  }
636  else {
637  dbg.nospace() << "\n";
638  }
639  dbg.nospace() << *it.current();
640  }
641  dbg.nospace() << "\n)";
642  return dbg.space();
643 }
644 
646 {
647  return d->previousSelection();
648 }
649 
651 {
652  d->setPreviousSelection(prevSelection);
653 }
654 
656 {
658  for (KPropertySetIterator it(*this); it.current(); ++it) {
659  result.insert(it.current()->name(), it.current()->value());
660  }
661  return result;
662 }
663 
665 {
666  for (KPropertySetIterator it(*this); it.current(); ++it) {
667  it.current()->clearModifiedFlag();
668  }
669 }
670 
672 {
673  for (KPropertySetIterator it(*this); it.current(); ++it) {
674  if (it.current()->isModified()) {
675  return true;
676  }
677  }
678  return false;
679 }
A class to iterate over a KPropertySet.
Definition: KPropertySet.h:57
void changeProperty(const QByteArray &property, const QVariant &value)
QString groupIconName(const QByteArray &group) const
QString groupCaption(const QByteArray &group) const
Order
Ordering options for properties.
Definition: KPropertySet.h:92
KPropertySetIterator(const KPropertySet &set)
Creates iterator for set set of properties.
void readOnlyFlagChanged()
bool isEmpty() const
bool hasVisibleProperties() const
QByteArray toLower() const const
KProperty * parent() const
Definition: KProperty.cpp:673
bool contains(const QByteArray &name) const
void changePropertyIfExists(const QByteArray &property, const QVariant &value)
void addProperty(KProperty *property, const QByteArray &group="common")
void removeProperty(KProperty *property)
const QObjectList & children() const const
void removeAt(int i)
bool isEmpty() const const
QDebug & nospace()
bool operator==(const KPropertySetIterator &other) const
QString tr(const char *sourceText, const char *disambiguation, int n)
void clearModifiedFlags()
Clears "modified" flag of all properties in this set, i.e.
void setOrder(Order order)
Sets order for properties. Restarts the iterator.
alphabetical order (case-insensitively by captions)
KPropertySet(QObject *parent=nullptr)
Constructs a new property set object.
T value(int i) const const
int indexOf(const T &value, int from) const const
bool operator==(const Qt3DRender::QGraphicsApiFilter &reference, const Qt3DRender::QGraphicsApiFilter &sample)
bool hasProperties(const KPropertySelector &selector) const
KIOCORE_EXPORT CopyJob * copy(const QUrl &src, const QUrl &dest, JobFlags flags=DefaultFlags)
QString caption() const
Definition: KProperty.cpp:336
QVariant propertyValue(const QByteArray &name, const QVariant &defaultValue=QVariant()) const
void append(const T &value)
KPropertySet & operator=(const KPropertySet &set)
void debug() const
QVariant property(const char *name) const const
bool isNull() const
Definition: KProperty.cpp:475
void setPreviousSelection(const QByteArray &prevSelection)
Sets previous section.
alphabetical order (case-insensitively by name)
An interface for functor selecting properties.
Definition: KPropertySet.h:35
CaseInsensitive
bool isEmpty() const const
void setObjectName(const QString &name)
int count() const
bool isEmpty() const const
bool isReadOnly() const
virtual KPropertySelector * clone() const =0
Creates a deep copy of the selector.
Set of properties.
Definition: KPropertySet.h:119
QByteArray name() const
Definition: KProperty.cpp:324
QList::iterator end()
void setGroupIconName(const QByteArray &group, const QString &iconName)
QDebug & space()
QByteArray previousSelection() const
void setGroupCaption(const QByteArray &group, const QString &caption)
bool isVisible() const
Definition: KProperty.cpp:520
The base class representing a single property.
Definition: KProperty.h:95
const QList< QKeySequence > & end()
QDataStream & operator<<(QDataStream &out, const KDateTime::Spec &spec)
QVariant value() const
Definition: KProperty.cpp:394
bool isModified() const
Returns true if at least one property in this set is modified, i.e.
Order order() const
void insert(int i, const T &value)
KProperty & property(const QByteArray &name) const
void aboutToBeCleared()
QList< QByteArray > groupNames() const
QMap::iterator insert(const Key &key, const T &value)
QList< QByteArray > propertyNamesForGroup(const QByteArray &group) const
QByteArray groupNameForProperty(const QByteArray &propertyName) const
void aboutToBeDeleted()
QMap< QByteArray, QVariant > propertyValues() const
bool setValue(const QVariant &value, ValueOptions options=ValueOptions())
Sets value of the property.
Definition: KProperty.cpp:405
int compare(const QString &other, Qt::CaseSensitivity cs) const const
const QList< KProperty * > * children() const
Definition: KProperty.cpp:656
QList::iterator begin()
KProperty & operator[](const QByteArray &name) const
void setReadOnly(bool readOnly)
KPropertySetIterator & operator=(const KPropertySetIterator &other)
Assigns other to this KPropertySetIterator.
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Tue Jul 14 2020 23:03:15 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.