Salome HOME
Copyright update: 2016
[modules/gui.git] / src / SUIT / SUIT_DataObject.cxx
1 // Copyright (C) 2007-2016  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 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 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 // File   : SUIT_DataObject.cxx
24 // Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com)
25
26 #include <QVariant>
27
28 #include "SUIT_DataObject.h"
29 #include "SUIT_DataObjectKey.h"
30 #include <cstdio>
31
32 SUIT_DataObject::Signal* SUIT_DataObject::mySignal = 0;
33
34 /*!
35   \class SUIT_DataObject
36   \brief Data object representing the data instance in the tree-like hierarchy.
37
38   Data object represents uniform data tree structure recommended to use in the
39   SUIT-based applications.
40 */
41
42 /*!
43   \brief Constructor.
44
45   Creates the data object with the specified parent.
46   To create the top-level object, pass 0 as parameter.
47
48   \param p parent object
49 */
50 SUIT_DataObject::SUIT_DataObject( SUIT_DataObject* p )
51 : myParent( 0 ),
52   myOpen( false ),
53   myCheck( false ),
54   myAutoDel( true ),
55   _modified( false )
56 {
57   setParent( p );
58   signal()->emitCreated( this );
59 }
60
61 /*!
62   \brief Destructor.
63
64   Destroys all the children if "auto-delete children" flag is set.
65 */
66 SUIT_DataObject::~SUIT_DataObject()
67 {
68   SUIT_DataObject* p = myParent;
69
70   myParent = 0;
71
72   if ( p )
73     p->removeChild( this );
74
75   signal()->emitDestroyed( this );
76
77   for ( DataObjectList::iterator it = myChildren.begin(); it != myChildren.end(); ++it )
78     (*it)->myParent = 0;
79
80   if ( autoDeleteChildren() )
81   {
82     for ( DataObjectList::iterator itr = myChildren.begin(); itr != myChildren.end(); ++itr )
83       delete *itr;
84   }
85 }
86
87 /*!
88   \brief Get the root object.
89   \return root object of the data tree
90 */
91 SUIT_DataObject* SUIT_DataObject::root() const
92 {
93   return parent() ? parent()->root() : (SUIT_DataObject*)this;
94 }
95
96 /*!
97   \brief Get the first child object.
98   \return first child object or 0 if there are no children
99   \sa lastChild()
100 */
101 SUIT_DataObject* SUIT_DataObject::firstChild() const
102 {
103   SUIT_DataObject* child = 0;
104   if ( !myChildren.isEmpty() )
105     child = myChildren.first();
106   return child;
107 }
108
109 /*!
110   \brief Get the last child object.
111   \return last child object or 0 if there are no children
112   \sa firstChild()
113 */
114 SUIT_DataObject* SUIT_DataObject::lastChild() const
115 {
116   SUIT_DataObject* child = 0;
117   if ( !myChildren.isEmpty() )
118     child = myChildren.last();
119   return child;
120 }
121
122 /*!
123   \brief Get the number of the child objects.
124   \return number of the children
125 */
126 int SUIT_DataObject::childCount() const
127 {
128   return myChildren.count();
129 }
130
131 /*!
132   \brief Get the index of the specified object in the child list.
133   \param obj child object
134   \return subobject position or -1 if it does not belong to this object
135 */
136 int SUIT_DataObject::childPos( const SUIT_DataObject* obj ) const
137 {
138   return myChildren.indexOf( (SUIT_DataObject*)obj );
139 }
140
141 /*!
142   \brief Moves the child position from current to new one.
143   \param theObj child object
144   \param theNewPos child objectnew position in the children list
145
146 */
147 void SUIT_DataObject::moveChildPos( SUIT_DataObject* theObj, int theNewPos)
148 {
149   if (myChildren.size() <= 1)  return;
150
151   int aNewPos = theNewPos;
152   if (aNewPos < 0) aNewPos = 0;
153   if (aNewPos > (myChildren.size() - 1)) aNewPos = myChildren.size() - 1;
154
155   if (myChildren.removeOne(theObj))
156     myChildren.insert(aNewPos, theObj);
157 }
158
159
160 /*!
161   \brief Get child object by the specified index.
162   \param idx child object index
163   \return child object or 0 if index is out of range
164 */
165 SUIT_DataObject* SUIT_DataObject::childObject( const int idx ) const
166 {
167   SUIT_DataObject* child = 0;
168
169   if ( idx >= 0 && idx < myChildren.count() )
170     child = myChildren.at( idx );
171
172   return child;
173 }
174
175 /*!
176   \brief Get the object level in the tree structure.
177
178   Root object has level 0.
179
180   \return object level.
181 */
182 int SUIT_DataObject::level() const
183 {
184   int lev = 0;
185   SUIT_DataObject* p = parent();
186   while ( p ) {
187     p = p->parent();
188     lev++;
189   }
190   return lev;
191 }
192
193 /*!
194   \brief Get the position of the data object in its parent's children list
195   \return data object position
196 */
197 int SUIT_DataObject::position() const
198 {
199   return myParent ? myParent->childPos( this ) : 0;
200 }
201
202 /*!
203   \brief Sets new position of the object in parent's list
204 */
205 void SUIT_DataObject::setPosition(int theNewPos)
206 {
207   if (theNewPos == position())  return;
208   if (!myParent)  return;
209   myParent->moveChildPos(this, theNewPos);
210 }
211
212 /*!
213   \brief Get the next sibling data object in the children list.
214   \return child object or 0 if there is no next sibling
215   \sa prevBrother()
216 */
217 SUIT_DataObject* SUIT_DataObject::nextBrother() const
218 {
219   return myParent ? myParent->childObject( myParent->childPos( this ) + 1 ) : 0;
220 }
221
222 /*!
223   \brief Get the previous sibling data object in the children list.
224   \return child object or 0 if there is no previous sibling
225   \sa nextBrother()
226 */
227 SUIT_DataObject* SUIT_DataObject::prevBrother() const
228 {
229   return myParent ? myParent->childObject( myParent->childPos( this ) - 1 ) : 0;
230 }
231
232 /*!
233   \brief Get "auto-delete children" flag.
234   \return \c true if the object should delete all its children on destroying
235   \sa setAutoDeleteChildren()
236 */
237 bool SUIT_DataObject::autoDeleteChildren() const
238 {
239   return myAutoDel;
240 }
241
242 /*!
243   \brief Set "auto-delete children" flag.
244
245   If this flag is on (default), the object will delete
246   all its children on destroying.
247
248   \param on new flag value
249   \sa autoDeleteChildren()
250 */
251 void SUIT_DataObject::setAutoDeleteChildren( const bool on )
252 {
253   myAutoDel = on;
254 }
255
256 /*!
257   \brief Get all children.
258
259   If parameter \a rec is \c true then function collects all
260   the children recursively.
261
262   \param lst returning list of children
263   \param rec if \c true collect all children recursively
264 */
265 void SUIT_DataObject::children( DataObjectList& lst, const bool rec ) const
266 {
267   for ( DataObjectList::const_iterator it = myChildren.begin(); it != myChildren.end(); ++it )
268   {
269     lst.append( *it );
270     if ( rec )
271       (*it)->children( lst, rec );
272   }
273 }
274
275 /*!
276   \brief Get all children.
277   \override
278
279   If parameter \a rec is \c true then function collects all
280   the children recursively.
281
282   \param rec if \c true collect all children recursively
283   \return list of children
284 */
285 DataObjectList SUIT_DataObject::children( const bool rec )
286 {
287   DataObjectList lst;
288   children( lst, rec );
289   return lst;
290 }
291
292 /*!
293   \brief Add new child object to the end of the children list.
294   \param obj child object being added
295 */
296 void SUIT_DataObject::appendChild( SUIT_DataObject* obj )
297 {
298   insertChild( obj, myChildren.count() );
299 }
300
301 /*!
302   \brief Insert new child object to the list of the children.
303   \param obj child object being added
304   \param position child position
305 */
306 void SUIT_DataObject::insertChild( SUIT_DataObject* obj, int position )
307 {
308   if ( !obj || myChildren.contains( obj ) )
309     return;
310
311   int pos = position < 0 ? myChildren.count() : position;
312   myChildren.insert( qMin( pos, (int)myChildren.count() ), obj );
313   obj->setParent( this );
314   signal()->emitInserted( obj, this );
315 }
316
317 /*!
318   \brief Insert new child object into the list of the children (faster version of insertChild without signal).
319   \param obj child object being added
320   \param position child position
321 */
322 void SUIT_DataObject::insertChildAtPos( SUIT_DataObject* obj, int position )
323 {
324   if ( !obj )return;
325   int pos = position < 0 ? myChildren.count() : position;
326   myChildren.insert( qMin( pos, (int)myChildren.count() ), obj );
327   obj->assignParent( this );
328 }
329
330 /*!
331   \brief Remove the specified child object reference.
332   \param obj child object being removed
333   \param del if \c true, the child object is destroyed
334 */
335 void SUIT_DataObject::removeChild( SUIT_DataObject* obj, const bool del )
336 {
337   if ( !obj )
338     return;
339
340   if ( myChildren.removeAll( obj ) ) {
341     signal()->emitRemoved( obj, this );
342     obj->setParent( 0 );
343
344     if ( del )
345       obj->deleteLater();
346   }
347 }
348
349 /*!
350   \brief Replace the specified child object by another object.
351   \param src child object being replaced
352   \param trg new child object
353   \param del if \c true, the previous object is destroyed
354   \return \c true if the object has been replaced
355 */
356 bool SUIT_DataObject::replaceChild( SUIT_DataObject* src, SUIT_DataObject* trg, const bool del )
357 {
358   if ( !src || !trg )
359     return false;
360
361   int idx = childPos( trg );
362   removeChild( trg );
363
364   int pos = childPos( src );
365   if ( pos < 0 )
366   {
367     if ( idx >= 0 )
368       insertChild( trg, idx );
369     return false;
370   }
371
372   insertChild( trg, pos );
373   removeChild( src );
374
375   if ( del )
376     src->deleteLater();
377
378   return true;
379 }
380
381 /*!
382   \brief Change the parent for all children from specified object to this one.
383   \param obj object which children to be reparented
384 */
385 void SUIT_DataObject::reparentChildren( const SUIT_DataObject* obj )
386 {
387   if ( !obj )
388     return;
389
390   DataObjectList lst;
391   obj->children( lst );
392   for ( DataObjectList::iterator it = lst.begin(); it != lst.end(); ++it )
393     (*it)->setParent( this );
394 }
395
396 /*!
397   \brief Get the parent object.
398   \return parent object or 0 if this is top-level item
399 */
400 SUIT_DataObject* SUIT_DataObject::parent() const
401 {
402   return myParent;
403 }
404
405 /*!
406   \brief Change the parent object.
407   \param p new parent object
408 */
409 void SUIT_DataObject::setParent( SUIT_DataObject* p )
410 {
411   if ( p == parent() )
412     return;
413
414   if ( parent() )
415     parent()->removeChild( this );
416
417   myParent = p;
418
419   if ( parent() )
420     parent()->appendChild( this );
421 }
422
423 void SUIT_DataObject::assignParent( SUIT_DataObject* p )
424 {
425   if ( p == myParent )
426     return;
427
428   myParent = p;
429 }
430
431 /*!
432   \brief Sets modification state of the object.
433
434   When the object has been modified (modified is set to true)
435   a signal is emitted to notify the tree model and eventually redraw the data object.
436
437   \param modified modified state 
438 */
439 void SUIT_DataObject::setModified(bool modified)
440 {
441   if ( _modified == modified )
442     return;
443
444   _modified = modified;
445   if ( _modified )
446     signal()->emitModified( this );
447 }
448
449 /*!
450   \brief Get data object name.
451
452   This method should be re-implemented in the subclasses.
453   Default implementation returns null string.
454
455   \return object name
456 */
457 QString SUIT_DataObject::name() const
458 {
459   return QString();
460 }
461
462 /*!
463   \brief Get object text data for the specified column.
464
465   This method can be re-implemented in the subclasses.
466   Default implementation returns null string.
467
468   Column with \a id = 0 (NameId) is supposed to be used
469   to get the object name (as it does the default implementation).
470
471   \param id column id
472   \return object text data
473 */
474 QString SUIT_DataObject::text( const int id ) const
475 {
476   return id == NameId ? name() : QString();
477 }
478
479 /*!
480   \brief Get data object icon for the specified column.
481
482   This method can be re-implemented in the subclasses.
483   Default implementation returns null pixmap.
484
485   The parameter \a id specifies the column identificator
486
487   \param id column id
488   \return object icon for the specified column
489 */
490 QPixmap SUIT_DataObject::icon( const int /*id*/ ) const
491 {
492   return QPixmap();
493 }
494
495 /*!
496   \brief Get data object color for the specified column.
497
498   This method can be re-implemented in the subclasses.
499   Default implementation returns null color.
500
501   The parameter \a id specifies the column identificator
502
503   \param role color role
504   \param id column id
505   \return object color for the specified column
506 */
507 QColor SUIT_DataObject::color( const ColorRole /*role*/, const int /*id*/ ) const
508 {
509   return QColor();
510 }
511
512 /*!
513   \brief Get data object tooltip for the specified column.
514
515   This method can be re-implemented in the subclasses.
516   Default implementation returns null string.
517
518   The parameter \a id specifies the column identificator
519   (to display, for example, in the tree view widget).
520
521   \param id column id
522   \return object tooltip for the specified column
523 */
524 QString SUIT_DataObject::toolTip( const int /*id*/ ) const
525 {
526   return QString();
527 }
528
529 /*!
530   \brief Get data object status tip for the specified column.
531
532   This method can be re-implemented in the subclasses.
533   Default implementation returns null string.
534
535   The parameter \a id specifies the column identificator
536
537   \param id column id
538   \return object status tip for the specified column
539 */
540 QString SUIT_DataObject::statusTip( const int /*id*/ ) const
541 {
542   return QString();
543 }
544
545 /*!
546   \brief Get data object "what's this" information for the
547          specified column.
548
549   This method can be re-implemented in the subclasses.
550   Default implementation returns null string.
551
552   The parameter \a id specifies the column identificator
553
554   \param id column id
555   \return object "what's this" information for the specified column
556 */
557 QString SUIT_DataObject::whatsThis( const int /*id*/ ) const
558 {
559   return QString();
560 }
561
562 /*!
563   \brief Get data object font for the specified column.
564
565   This method can be re-implemented in the subclasses.
566   Default implementation returns application default font.
567
568   The parameter \a id specifies the column identificator
569
570   \param id column id
571   \return object font for the specified column
572 */
573 QFont SUIT_DataObject::font( const int /*id*/ ) const
574 {
575   return QFont();
576 }
577
578 /*!
579   \brief Get data object text alignment for the specified column.
580
581   This method can be re-implemented in the subclasses.
582   Default implementation returns default alignment which
583   is Qt:AlignLeft.
584
585   The parameter \a id specifies the column identificator
586   (to display, for example, in the tree view widget).
587
588   \param id column id
589   \return object text alignment flags for the specified column
590 */
591 int SUIT_DataObject::alignment( const int /*id*/ ) const
592 {
593   return Qt::AlignLeft;
594 }
595
596 bool SUIT_DataObject::expandable() const
597 {
598   return true;
599 }
600
601 /*!
602   \brief Check if the object is visible.
603
604   This method can be re-implemented in the subclasses.
605   Default implementation returns \c true (all objects are visible by default).
606
607   \return \c true if this object is displayable or \c false otherwise
608 */
609 bool SUIT_DataObject::isVisible() const
610 {
611   return true;
612 }
613
614 /*!
615   \brief Check if the object is draggable.
616
617   This method can be re-implemented in the subclasses.
618   Default implementation returns \c false (all objects could not be dragged).
619
620   \return \c true if it is possible to drag this object
621 */
622 bool SUIT_DataObject::isDraggable() const
623 {
624   return false;
625 }
626
627 /*!
628   \brief Check if the drop operation for this object is possible.
629
630   This method can be re-implemented in the subclasses.
631   Default implementation returns \c false (drop operation is not allowed).
632
633   \return \c true if it is possible to drop one or more objects (currently selected) to this object
634 */
635 bool SUIT_DataObject::isDropAccepted() const
636 {
637   return false;
638 }
639
640 /*!
641   \brief Check if this object is enabled.
642
643   This method can be re-implemented in the subclasses.
644   Default implementation returns \c true (all objects are enabled).
645
646   \return \c true if the user can interact with the item
647 */
648 bool SUIT_DataObject::isEnabled() const
649 {
650   return true;
651 }
652
653 /*!
654   \brief Check if this object is selectable.
655
656   This method can be re-implemented in the subclasses.
657   Default implementation returns \c true (all objects are selectable).
658
659   \return \c true if the item can be selected
660 */
661 bool SUIT_DataObject::isSelectable() const
662 {
663   return true;
664 }
665
666 /*!
667   \brief Check if this object is checkable for the specified column.
668
669   This method can be re-implemented in the subclasses.
670   Default implementation returns \c false (all objects are not checkable).
671
672   \param id column id
673   \return \c true if the item can be checked or unchecked by the user
674   \sa isOn(), setOn()
675 */
676 bool SUIT_DataObject::isCheckable( const int /*id*/ ) const
677 {
678   return false;
679 }
680
681 /*!
682   \brief Check if this object is can't be renamed in place
683
684   This method can be re-implemented in the subclasses.
685   Default implementation returns \c false (all objects can not be renamed).
686
687   \param id column id
688   \return \c true if the item can be renamed by the user in place (e.g. in the Object browser)
689 */
690 bool SUIT_DataObject::renameAllowed( const int /*id*/ ) const
691 {
692   return false;
693 }
694
695 /*!
696   \brief Set name of the this object.
697
698   This method can be re-implemented in the subclasses.
699   Default implementation returns \c false.
700
701   \return \c true if rename operation finished successfully, \c false otherwise.
702 */
703 bool SUIT_DataObject::setName(const QString& /*name*/) {
704   return false;
705 }
706
707 /*!
708   \brief Get the checked state of the object (if it is checkable)
709   for the specified column.
710
711   Default implementation supports the checked state for the first
712   ("Name") column only.
713
714   \param id column id
715   \return checked state of the object for the specified column
716   \sa setOn(), isCheckable()
717 */
718 bool SUIT_DataObject::isOn( const int id ) const
719 {
720   return id == NameId && myCheck;
721 }
722
723 /*!
724   \brief Set the checked state of the object (if it is checkable)
725   for the specified column.
726
727   Default implementation supports the checked state for the first
728   ("Name") column only.
729
730   \param on new checked state of the object for the specified column
731   \param id column id
732   \sa isOn(), isCheckable()
733 */
734 void SUIT_DataObject::setOn( const bool on, const int id )
735 {
736   if( id == NameId )
737     myCheck = on;
738 }
739
740 /*!
741   \brief Get the "opened" state of the object.
742   \return "opened" state of the object
743   \sa setOpen()
744 */
745 bool SUIT_DataObject::isOpen() const
746 {
747   return myOpen;
748 }
749
750 /*!
751   \brief Set the "opened" state of the object.
752   \param on new "opened" state of the object
753   \sa isOpen()
754 */
755 void SUIT_DataObject::setOpen( const bool on )
756 {
757   myOpen = on;
758 }
759
760 /*!
761   \brief Check if the specified column supports custom sorting.
762
763   This method can be re-implemented in the subclasses.
764   Default implementation returns false ("Name" column does not require
765   custom sorting).
766
767   \param id column id
768   \return \c true if column sorting should be customized
769   \sa compare()
770 */
771 bool SUIT_DataObject::customSorting( const int /*id*/ ) const
772 {
773   return false;
774 }
775
776 /*!
777   \brief Compares data from two items for sorting purposes.
778
779   This method can be re-implemented in the subclasses.
780   Default implementation returns false ("Name" column does not require
781   custom sorting).
782
783   This method is called only for those columns for which customSorting()
784   method returns \c true.
785
786   \param left first data to compare
787   \param right second data to compare
788   \param id column id
789   \return result of the comparison
790   \sa customSorting()
791 */
792 bool SUIT_DataObject::compare( const QVariant& /*left*/, const QVariant& /*right*/,
793                                const int /*id*/ ) const
794 {
795   return false;
796 }
797
798 /*!
799   \brief Get the object unique indentification key.
800
801   This method can be re-implemented in the subclasses.
802   Default implementation returns 0.
803
804   \return object key
805 */
806 SUIT_DataObjectKey* SUIT_DataObject::key() const
807 {
808   return 0;
809 }
810
811 /*!
812   \brief Get global signal handler.
813   \return the only instance of the signal handler
814 */
815 SUIT_DataObject::Signal* SUIT_DataObject::signal()
816 {
817   if ( !mySignal )
818     mySignal = new Signal();
819   return mySignal;
820 }
821
822 /*!
823   \brief Connect to the signal handlerx
824   \param sig signal name
825   \param reciever signal receiver object
826   \param slot slot name
827   \return \c true if connection is successfull
828 */
829 bool SUIT_DataObject::connect( const char* sig, QObject* reciever, const char* slot )
830 {
831   if ( !reciever || !slot )
832     return false;
833
834   signal()->disconnect( signal(), sig, reciever, slot );
835   return signal()->connect( signal(), sig, reciever, slot );
836 }
837
838 /*!
839   \brief Disconnect from the signal handler
840   \param sig signal name
841   \param reciever signal receiver object
842   \param slot slot name
843   \return \c true if disconnection is successfull
844 */
845 bool SUIT_DataObject::disconnect( const char* sig, QObject* reciever, const char* slot )
846 {
847   if ( !reciever || !slot )
848     return false;
849   return signal()->disconnect( signal(), sig, reciever, slot );
850 }
851
852 /*!
853   \brief Schedule this object for the late deleting.
854
855   The object will be deleted when control returns to the event loop.
856   Note that entering and leaving a new event loop (e.g., by opening
857   a modal dialog) will not perform the deferred deletion; for the object
858   to be deleted, the control must return to the event loop from which
859   deleteLater() was called.
860 */
861 void SUIT_DataObject::deleteLater()
862 {
863   if ( parent() )
864     parent()->removeChild( this, false ); // to avoid infinite loop!
865   signal()->deleteLater( this );
866 }
867
868 /*!
869   \brief Dump the object tree recursively to the standard output.
870   \param indent current indentation level
871 */
872 void SUIT_DataObject::dump( const int indent ) const
873 {
874   QString strIndent = QString().fill( ' ', indent ); // indentation string
875   printf( "%s%s\n", strIndent.toLatin1().data(), name().toLatin1().data() );
876   for ( DataObjectList::const_iterator it = myChildren.begin(); it != myChildren.end(); ++it )
877     (*it)->dump( indent + 2 );
878 }
879
880 /*!
881   \class SUIT_DataObject::Signal
882   \brief Watcher class, responsible for the emitting signals on behalf of
883   the data objects.
884
885   SUIT_DataObject class does not inherit from QObject for the performance
886   reasons, so it can not use signals/slots mechanism directly.
887   Instead it uses the only Signal object to emit the signals when the data
888   object is created, destroyed, inserted to the parent object or removed
889   from it.
890
891   If some object needs to handle, for example, data object destroying, it can
892   use SUIT_DataObject::signal() method to connect the signal:
893   \code
894   MyHandler* h = new MyHandler();
895   h->connect( SUIT_DataObject::signal(), SIGNAL(destroyed(SUIT_DataObject*)),
896               h, SLOT(onDestroyed(SUIT_DataObject*)) );
897   \endcode
898   The same can be done by using static method SUIT_DataObject::connect().
899   For example,
900   \code
901   MyHandler* h = new MyHandler();
902   SUIT_DataObject::connect( SIGNAL(destroyed(SUIT_DataObject*)),
903                             h, SLOT(onDestroyed(SUIT_DataObject*)));
904   \endcode
905 */
906
907 /*!
908   \brief Constructor.
909 */
910 SUIT_DataObject::Signal::Signal()
911 : QObject()
912 {
913 }
914
915 /*!
916   \brief Destructor.
917
918   Destroys data object which are scheduled for the deleting with the deleteLater().
919 */
920 SUIT_DataObject::Signal::~Signal()
921 {
922   for ( DataObjectList::Iterator it = myDelLaterObjects.begin();
923         it != myDelLaterObjects.end(); ++it ) {
924     delete *it;
925   }
926   myDelLaterObjects.clear();
927 }
928
929 /*!
930   \brief Emit signal about data object creation.
931   \param object data object being created
932 */
933 void SUIT_DataObject::Signal::emitCreated( SUIT_DataObject* object )
934 {
935   if ( object )
936     emit created( object );
937 }
938
939 /*!
940   \brief Emit signal about data object destroying.
941   \param object data object being destroyed
942 */
943 void SUIT_DataObject::Signal::emitDestroyed( SUIT_DataObject* object )
944 {
945   if ( object ) {
946     if ( myDelLaterObjects.contains( object ) )
947       // object is being destroyed after calling deleteLater():
948       // the signal has been already emitted from deleteLater()
949       // we should avoid repeating of the object destroying from
950       // the Signal destructor
951       myDelLaterObjects.removeAll( object );
952     else
953       // object is being destroyed directly or via deleteLater()
954       emit destroyed( object );
955   }
956 }
957
958 /*!
959   \brief Emit signal about data object adding to the parent data object.
960   \param object data object being added
961   \param parent parent data object
962 */
963 void SUIT_DataObject::Signal::emitInserted( SUIT_DataObject* object, SUIT_DataObject* parent )
964 {
965   emit( inserted( object, parent ) );
966 }
967
968 /*!
969   \brief Emit signal about data object removed from the parent data object.
970   \param object data object being removed
971   \param parent parent data object
972 */
973 void SUIT_DataObject::Signal::emitRemoved( SUIT_DataObject* object, SUIT_DataObject* parent )
974 {
975   emit( removed( object, parent ) );
976 }
977
978 /*!
979   \brief Emit a signal to notify that the data object has been modified.
980   \param object data object that has been modified
981 */
982 void SUIT_DataObject::Signal::emitModified( SUIT_DataObject* object )
983 {
984   emit( modified( object ) );
985 }
986
987 /*!
988   \brief Schedule data object for the late deleting.
989   \param object data object to be deleted later
990 */
991 void SUIT_DataObject::Signal::deleteLater( SUIT_DataObject* object )
992 {
993   if ( !myDelLaterObjects.contains( object ) ) {
994     emitDestroyed( object );
995     myDelLaterObjects.append( object );
996   }
997 }
998
999 /*!
1000   \brief Updates necessary internal fields of data object
1001 */
1002 void SUIT_DataObject::update()
1003 {
1004 }
1005
1006 /*!
1007   \brief return unique group identificator
1008
1009   Groups of data objects are used for column information search.
1010   Each column of data model has one or several registered group id
1011   If object has the same group id as one of registered, the information
1012   will be shown; the custom id of column will be passed into data() method
1013   in order to identify column from point of view of data object
1014
1015  */
1016 int SUIT_DataObject::groupId() const
1017 {
1018   return 0;
1019 }
1020 /*!
1021   \brief return custom data for data object.
1022  */
1023 QVariant SUIT_DataObject::customData(Qtx::CustomDataType /*type*/) {
1024   return QVariant();
1025 }
1026 /*!
1027   \fn void SUIT_DataObject::Signal::created( SUIT_DataObject* object );
1028   \brief Emitted when data object is created.
1029   \param object data object being created
1030 */
1031
1032 /*!
1033   \fn void SUIT_DataObject::Signal::destroyed( SUIT_DataObject* object );
1034   \brief Emitted when data object is destroyed.
1035   \param object data object being destroyed
1036 */
1037
1038 /*!
1039   \fn void SUIT_DataObject::Signal::inserted( SUIT_DataObject* object, SUIT_DataObject* parent );
1040   \brief Emitted when data object is inserted to the parent data object.
1041   \param object data object being created
1042   \param parent parent data object
1043 */
1044
1045 /*!
1046   \fn void SUIT_DataObject::Signal::removed( SUIT_DataObject* object, SUIT_DataObject* parent );
1047   \brief Emitted when data object is removed from the parent data object.
1048   \param object data object being removed
1049   \param parent parent data object
1050 */