property.cpp
1/* This file is part of the KDE project
2 Copyright (C) 2004 Cedric Pasteur <cedric.pasteur@free.fr>
3 Copyright (C) 2004 Alexander Dymo <cloudtemple@mskat.net>
4 Copyright (C) 2004-2006 Jaroslaw Staniek <js@iidea.pl>
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 "property.h"
23#include "customproperty.h"
24#include "set.h"
25#include "factory.h"
26
27#include <kdebug.h>
28
29#include <tqobject.h>
30#include <tqptrdict.h>
31#include <tqasciidict.h>
32#include <tqguardedptr.h>
33
34namespace KoProperty {
35
37
39class PropertyPrivate
40{
41 public:
42 PropertyPrivate()
43 : caption(0), listData(0), changed(false), storable(true),
44 readOnly(false), visible(true),
45 autosync(-1), custom(0), useCustomProperty(true),
46 sets(0), parent(0), children(0), relatedProperties(0),
47 sortingKey(0)
48 {
49 }
50
51 inline void setCaptionForDisplaying(const TQString& captionForDisplaying)
52 {
53 delete caption;
54 if (captionForDisplaying.simplifyWhiteSpace()!=captionForDisplaying)
55 caption = new TQString(captionForDisplaying.simplifyWhiteSpace());
56 else
57 caption = 0;
58 this->captionForDisplaying = captionForDisplaying;
59 }
60
61 ~PropertyPrivate()
62 {
63 delete caption;
64 caption = 0;
65 delete listData;
66 delete children;
67 delete relatedProperties;
68 delete custom;
69 delete sets;
70 }
71
72 int type;
73 TQCString name;
74 TQString captionForDisplaying;
75 TQString* caption;
76 TQString description;
77 TQVariant value;
78 TQVariant oldValue;
80 Property::ListData* listData;
81// TQStringVariantMap *valueList;
82 TQString icon;
83
84 bool changed : 1;
85 bool storable : 1;
86 bool readOnly : 1;
87 bool visible : 1;
88 int autosync;
89 TQMap<TQCString, TQVariant> options;
90
91 CustomProperty *custom;
93 bool useCustomProperty;
94
96 TQGuardedPtr<Set> set;
98 TQPtrDict< TQGuardedPtr<Set> > *sets;
99// TQValueList<Set*> sets;
100
101 Property *parent;
102 TQValueList<Property*> *children;
104 TQValueList<Property*> *relatedProperties;
105
106 int sortingKey;
107};
108}
109
110using namespace KoProperty;
111
113
114Property::ListData::ListData(const TQStringList& keys_, const TQStringList& names_)
115 : names(names_)
116// , fixed(true)
117{
118 setKeysAsStringList(keys_);
119}
120
121Property::ListData::ListData(const TQValueList<TQVariant> keys_, const TQStringList& names_)
122 : keys(keys_), names(names_)
123// , fixed(true)
124{
125}
126
127Property::ListData::ListData()
128// : fixed(true)
129{
130}
131
132Property::ListData::~ListData()
133{
134}
135
136void Property::ListData::setKeysAsStringList(const TQStringList& list)
137{
138 keys.clear();
139 for (TQStringList::ConstIterator it = list.constBegin(); it!=list.constEnd(); ++it) {
140 keys.append(*it);
141 }
142}
143
144TQStringList Property::ListData::keysAsStringList() const
145{
146 TQStringList result;
147 for (TQValueList<TQVariant>::ConstIterator it = keys.constBegin(); it!=keys.constEnd(); ++it) {
148 result.append((*it).toString());
149 }
150 return result;
151}
152
154
155/*
156KOPROPERTY_EXPORT TQStringVariantMap
157KoProperty::createValueListFromStringLists(const TQStringList &keys, const TQStringList &values)
158{
159 TQStringVariantMap map;
160 if(keys.count() != values.count())
161 return map;
162
163 TQStringList::ConstIterator valueIt = values.begin();
164 TQStringList::ConstIterator endIt = keys.constEnd();
165 for(TQStringList::ConstIterator it = keys.begin(); it != endIt; ++it, ++valueIt)
166 map.insert( *it, *valueIt);
167
168 return map;
169}
170*/
171
172
173Property::Property(const TQCString &name, const TQVariant &value,
174 const TQString &caption, const TQString &description,
175 int type, Property* parent)
176 : d( new PropertyPrivate() )
177{
178 d->name = name;
179 d->setCaptionForDisplaying(caption);
180 d->description = description;
181
182 if(type == Auto)
183 d->type = value.type();
184 else
185 d->type = type;
186
187 d->custom = FactoryManager::self()->createCustomProperty(this);
188
189 if (parent)
190 parent->addChild(this);
191 setValue(value, false);
192}
193
194Property::Property(const TQCString &name, const TQStringList &keys, const TQStringList &strings,
195 const TQVariant &value, const TQString &caption, const TQString &description,
196 int type, Property* parent)
197 : d( new PropertyPrivate() )
198{
199 d->name = name;
200 d->setCaptionForDisplaying(caption);
201 d->description = description;
202 d->type = type;
203 setListData(keys, strings);
204
205 d->custom = FactoryManager::self()->createCustomProperty(this);
206
207 if (parent)
208 parent->addChild(this);
209 setValue(value, false);
210}
211
212Property::Property(const TQCString &name, ListData* listData,
213 const TQVariant &value, const TQString &caption, const TQString &description,
214 int type, Property* parent)
215 : d( new PropertyPrivate() )
216{
217 d->name = name;
218 d->setCaptionForDisplaying(caption);
219 d->description = description;
220 d->type = type;
221 d->listData = listData;
222
223 d->custom = FactoryManager::self()->createCustomProperty(this);
224
225 if (parent)
226 parent->addChild(this);
227 setValue(value, false);
228}
229
231 : d( new PropertyPrivate() )
232{
233}
234
236 : d( new PropertyPrivate() )
237{
238 *this = prop;
239}
240
241Property::~Property()
242{
243 delete d;
244 d = 0;
245}
246
247TQCString
249{
250 return d->name;
251}
252
253void
254Property::setName(const TQCString &name)
255{
256 d->name = name;
257}
258
259TQString
261{
262 return d->caption ? *d->caption : d->captionForDisplaying;
263}
264
265TQString
267{
268 return d->captionForDisplaying;
269}
270
271void
272Property::setCaption(const TQString &caption)
273{
274 d->setCaptionForDisplaying(caption);
275}
276
277TQString
279{
280 return d->description;
281}
282
283void
284Property::setDescription(const TQString &desc)
285{
286 d->description = desc;
287}
288
289int
291{
292 return d->type;
293}
294
295void
297{
298 d->type = type;
299}
300
301TQString
303{
304 return d->icon;
305}
306
307void
308Property::setIcon(const TQString &icon)
309{
310 d->icon = icon;
311}
312
313TQVariant
315{
316 if(d->custom && d->custom->handleValue())
317 return d->custom->value();
318 return d->value;
319}
320
321TQVariant
323{
324/* if(d->oldValue.isNull())
325 return value();
326 else*/
327 return d->oldValue;
328}
329
330void
331Property::setValue(const TQVariant &value, bool rememberOldValue, bool useCustomProperty)
332{
333 if (d->name.isEmpty()) {
334 kopropertywarn << "Property::setValue(): COULD NOT SET value to a null property" << endl;
335 return;
336 }
337 TQVariant currentValue = this->value();
338 const TQVariant::Type t = currentValue.type();
339 const TQVariant::Type newt = value.type();
340// kopropertydbg << d->name << " : setValue('" << value.toString() << "' type=" << type() << ")" << endl;
341 if (t != newt && !currentValue.isNull() && !value.isNull()
342 && !( (t==TQVariant::Int && newt==TQVariant::UInt)
343 || (t==TQVariant::UInt && newt==TQVariant::Int)
344 || (t==TQVariant::CString && newt==TQVariant::String)
345 || (t==TQVariant::String && newt==TQVariant::CString)
346 || (t==TQVariant::ULongLong && newt==TQVariant::LongLong)
347 || (t==TQVariant::LongLong && newt==TQVariant::ULongLong)
348 )) {
349 kopropertywarn << "Property::setValue(): INCOMPATIBLE TYPES! old=" << currentValue
350 << " new=" << value << endl;
351 }
352
353 //1. Check if the value should be changed
354 bool ch;
355 if (t == TQVariant::DateTime
356 || t == TQVariant::Time) {
357 //for date and datetime types: compare with strings, because there
358 //can be miliseconds difference
359 ch = (currentValue.toString() != value.toString());
360 }
361 else if (t == TQVariant::String || t==TQVariant::CString) {
362 //property is changed for string type,
363 //if one of value is empty and other isn't..
364 ch = ( (currentValue.toString().isEmpty() != value.toString().isEmpty())
365 //..or both are not empty and values differ
366 || (!currentValue.toString().isEmpty() && !value.toString().isEmpty() && currentValue != value) );
367 }
368 else if (t == TQVariant::Invalid && newt == TQVariant::Invalid)
369 ch = false;
370 else
371 ch = (currentValue != value);
372
373 if (!ch)
374 return;
375
376 //2. Then change it, and store old value if necessary
377 if(rememberOldValue) {
378 if(!d->changed)
379 d->oldValue = currentValue;
380 d->changed = true;
381 }
382 else {
383 d->oldValue = TQVariant(); // clear old value
384 d->changed = false;
385 }
386 TQVariant prevValue;
387 if(d->custom && useCustomProperty) {
388 d->custom->setValue(value, rememberOldValue);
389 prevValue = d->custom->value();
390 }
391 else
392 prevValue = currentValue;
393
394 if (!d->custom || !useCustomProperty || !d->custom->handleValue())
395 d->value = value;
396
397 emitPropertyChanged(); // called as last step in this method!
398}
399
400void
402{
403 d->changed = false;
404 bool cleared = false;
405 if (d->set)
406 d->set->informAboutClearing(cleared); //inform me about possibly clearing the property sets
407 setValue(oldValue(), false);
408 if (cleared)
409 return; //property set has been cleared: no further actions make sense as 'this' is dead
410
411 // maybe parent prop is also unchanged now
412 if(d->parent && d->parent->value() == d->parent->oldValue())
413 d->parent->d->changed = false;
414
415 if (d->sets) {
416 for (TQPtrDictIterator< TQGuardedPtr<Set> > it(*d->sets); it.current(); ++it) {
417 if (it.current()) //may be destroyed in the meantime
418 emit (*it.current())->propertyReset(**it.current(), *this);
419 }
420 }
421 else if (d->set) {
422 emit d->set->propertyReset(*d->set, *this);
423 }
424}
425
426//const TQStringVariantMap*
429{
430 return d->listData;
431}
432
433void
434Property::setListData(ListData* list) //const TQStringVariantMap &list)
435{
436// if(!d->valueList)
437// d->valueList = new TQStringVariantMap();
438 if (list == d->listData)
439 return;
440 delete d->listData;
441 d->listData = list;
442}
443
444void
445Property::setListData(const TQStringList &keys, const TQStringList &names)
446{
447 ListData* list = new ListData(keys, names);
448 setListData(list);
449
450// if(!d->valueList)
451// d->valueList = new TQStringVariantMap();
452// *(d->valueList) = createValueListFromStringLists(keys, values);
453}
454
456
457bool
459{
460 return d->name.isEmpty();
461}
462
463bool
465{
466 return d->changed;
467}
468
469void
471{
472 d->changed = false;
473}
474
475bool
477{
478 return d->readOnly;
479}
480
481void
483{
484 d->readOnly = readOnly;
485}
486
487bool
489{
490 return d->visible;
491}
492
493void
495{
496 d->visible = visible;
497}
498
499int
501{
502 return d->autosync;
503}
504
505void
507{
508 d->autosync = sync;
509}
510
511bool
513{
514 return d->storable;
515}
516
517void
519{
520 d->storable = storable;
521}
522
523void
524Property::setOption(const char* name, const TQVariant& val)
525{
526 d->options[name] = val;
527}
528
529TQVariant
530Property::option(const char* name) const
531{
532 if (d->options.contains(name))
533 return d->options[name];
534 return TQVariant();
535}
536
537bool
539{
540 return !d->options.isEmpty();
541}
542
544
545Property::operator bool () const
546{
547 return !isNull();
548}
549
550const Property&
551Property::operator= (const TQVariant& val)
552{
553 setValue(val);
554 return *this;
555}
556
557const Property&
559{
560 if(&property == this)
561 return *this;
562
563 if(d->listData) {
564 delete d->listData;
565 d->listData = 0;
566 }
567 if(d->children) {
568 delete d->children;
569 d->children = 0;
570 }
571 if(d->relatedProperties) {
572 delete d->relatedProperties;
573 d->relatedProperties = 0;
574 }
575 if(d->custom) {
576 delete d->custom;
577 d->custom = 0;
578 }
579
580 d->name = property.d->name;
581 d->setCaptionForDisplaying(property.captionForDisplaying());
582 d->description = property.d->description;
583 d->type = property.d->type;
584
585 d->icon = property.d->icon;
586 d->autosync = property.d->autosync;
587 d->visible = property.d->visible;
588 d->storable = property.d->storable;
589 d->readOnly = property.d->readOnly;
590 d->options = property.d->options;
591
592 if(property.d->listData) {
593 d->listData = new ListData(*property.d->listData); //TQStringVariantMap(*(property.d->valueList));
594 }
595 if(property.d->custom) {
596 d->custom = FactoryManager::self()->createCustomProperty(this);
597 // updates all children value, using CustomProperty
598 setValue(property.value());
599 }
600 else {
601 d->value = property.d->value;
602 if(property.d->children) {
603 // no CustomProperty (should never happen), simply copy all children
604 d->children = new TQValueList<Property*>();
605 TQValueList<Property*>::ConstIterator endIt = property.d->children->constEnd();
606 for(TQValueList<Property*>::ConstIterator it = property.d->children->constBegin(); it != endIt; ++it) {
607 Property *child = new Property( *(*it) );
609 }
610 }
611 }
612
613 if(property.d->relatedProperties) {
614 d->relatedProperties = new TQValueList<Property*>( *(property.d->relatedProperties));
615 }
616
617 // update these later because they may have been changed when creating children
618 d->oldValue = property.d->oldValue;
619 d->changed = property.d->changed;
620 d->sortingKey = property.d->sortingKey;
621
622 return *this;
623}
624
625bool
627{
628 return ((d->name == prop.d->name) && (value() == prop.value()));
629}
630
632
633const TQValueList<Property*>*
635{
636 return d->children;
637}
638
640Property::child(const TQCString &name)
641{
642 TQValueList<Property*>::ConstIterator endIt = d->children->constEnd();
643 for(TQValueList<Property*>::ConstIterator it = d->children->constBegin(); it != endIt; ++it) {
644 if((*it)->name() == name)
645 return *it;
646 }
647 return 0;
648}
649
652{
653 return d->parent;
654}
655
656void
658{
659 if (!prop)
660 return;
661
662 if(!d->children || tqFind( d->children->begin(), d->children->end(), prop) == d->children->end()) { // not in our list
663 if(!d->children)
664 d->children = new TQValueList<Property*>();
665 d->children->append(prop);
666 prop->setSortingKey(d->children->count());
667 prop->d->parent = this;
668 }
669 else {
670 kopropertywarn << "Property::addChild(): property \"" << name()
671 << "\": child property \"" << prop->name() << "\" already added" << endl;
672 return;
673 }
674}
675
676void
678{
679 if (!set)
680 return;
681
682 if (!d->set) {//simple case
683 d->set = set;
684 return;
685 }
686 if ((Set*)d->set==set)
687 return;
688 TQGuardedPtr<Set> *pset = d->sets ? d->sets->find(set) : 0;
689 if (pset && (Set*)*pset == set)
690 return;
691 if (!d->sets) {
692 d->sets = new TQPtrDict< TQGuardedPtr<Set> >( 101 );
693 d->sets->setAutoDelete(true);
694 }
695
696 d->sets->replace(set, new TQGuardedPtr<Set>( set ));
697
698// TQValueList<Set*>::iterator it = tqFind( d->sets.begin(), d->sets.end(), set);
699// if(it == d->sets.end()) // not in our list
700// d->sets.append(set);
701}
702
703const TQValueList<Property*>*
705{
706 return d->relatedProperties;
707}
708
709void
711{
712 if(!d->relatedProperties)
713 d->relatedProperties = new TQValueList<Property*>();
714
715 TQValueList<Property*>::iterator it = tqFind( d->relatedProperties->begin(), d->relatedProperties->end(), property);
716 if(it == d->relatedProperties->end()) // not in our list
717 d->relatedProperties->append(property);
718}
719
722{
723 return d->custom;
724}
725
726void
728{
729 d->custom = prop;
730}
731
733{
734 return d->sortingKey;
735}
736
738{
739 d->sortingKey = key;
740}
741
743{
744 if (d->sets) {
745 for (TQPtrDictIterator< TQGuardedPtr<Set> > it(*d->sets); it.current(); ++it) {
746 if (it.current()) {//may be destroyed in the meantime
747 emit (*it.current())->propertyChangedInternal(**it.current(), *this);
748 emit (*it.current())->propertyChanged(**it.current(), *this);
749 }
750 }
751 }
752 else if (d->set) {
753 //if the slot connect with that signal may call set->clear() - that's
754 //the case e.g. at kexi/plugins/{macros|scripting}/* - this Property
755 //may got destroyed ( see Set::removeProperty(Property*) ) while we are
756 //still on it. So, if we try to access ourself/this once the signal
757 //got emitted we may end in a very hard to reproduce crash. So, the
758 //emit should happen as last step in this method!
759 emit d->set->propertyChangedInternal(*d->set, *this);
760 emit d->set->propertyChanged(*d->set, *this);
761 }
762}
763
765
766void
768{
769 TQString dbg = "Property( name='" + TQString(d->name) + "' desc='" + d->description
770 + "' val=" + (value().isValid() ? value().toString() : "<INVALID>");
771 if (!d->oldValue.isValid())
772 dbg += (", oldVal='" + d->oldValue.toString() + '\'');
773 dbg += (TQString(d->changed ? " " : " un") + "changed");
774 dbg += (d->visible ? " visible" : " hidden");
775 dbg+=" )";
776
777 kopropertydbg << dbg << endl;
778}
Base class for custom properties.
static FactoryManager * self()
Definition factory.cpp:93
CustomProperty * createCustomProperty(Property *parent)
Definition factory.cpp:244
The base class representing a single property.
Definition property.h:177
void setSortingKey(int key)
Definition property.cpp:737
void addSet(Set *set)
Definition property.cpp:677
void setAutoSync(int sync)
Definition property.cpp:506
void setType(int type)
Definition property.cpp:296
TQCString name() const
Definition property.cpp:248
TQString icon() const
Definition property.cpp:302
CustomProperty * customProperty() const
Definition property.cpp:721
bool isReadOnly() const
Definition property.cpp:476
void setStorable(bool storable)
Definition property.cpp:518
const Property & operator=(const TQVariant &val)
Definition property.cpp:551
bool isModified() const
Definition property.cpp:464
Property * child(const TQCString &name)
Definition property.cpp:640
bool isNull() const
Definition property.cpp:458
const TQValueList< Property * > * children() const
Definition property.cpp:634
ListData * listData() const
Definition property.cpp:428
TQVariant option(const char *name) const
Definition property.cpp:530
Property * parent() const
Definition property.cpp:651
static const Property null
A contant for null property.
Definition property.h:180
void addRelatedProperty(Property *property)
Definition property.cpp:710
void clearModifiedFlag()
Clears "modified" flag, so isModified() will return false.
Definition property.cpp:470
TQVariant value() const
Definition property.cpp:314
void setReadOnly(bool readOnly)
Definition property.cpp:482
void setCaption(const TQString &caption)
Definition property.cpp:272
void addChild(Property *prop)
Definition property.cpp:657
TQString description() const
Definition property.cpp:278
void setName(const TQCString &name)
Definition property.cpp:254
void setVisible(bool visible)
Definition property.cpp:494
bool isStorable() const
Definition property.cpp:512
void setValue(const TQVariant &value, bool rememberOldValue=true, bool useCustomProperty=true)
Definition property.cpp:331
const TQValueList< Property * > * related() const
Definition property.cpp:704
bool hasOptions() const
Definition property.cpp:538
int autoSync() const
Definition property.cpp:500
TQString caption() const
Definition property.cpp:260
int sortingKey() const
Definition property.cpp:732
TQString captionForDisplaying() const
Definition property.cpp:266
bool operator==(const Property &prop) const
Definition property.cpp:626
void setListData(ListData *list)
Definition property.cpp:434
TQVariant oldValue() const
Definition property.cpp:322
void setCustomProperty(CustomProperty *prop)
Definition property.cpp:727
void setOption(const char *name, const TQVariant &val)
Definition property.cpp:524
void setDescription(const TQString &description)
Definition property.cpp:284
void setIcon(const TQString &icon)
Definition property.cpp:308
bool isVisible() const
Definition property.cpp:488
Lists holding properties in groups.
Definition set.h:41
const char * name(StdAction id)
Namespace for a set of classes implementing generic properties framework.