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