Salome HOME
Updated copyright comment
[modules/gui.git] / src / SUIT / SUIT_DataObject.cxx
1 // Copyright (C) 2007-2024  CEA, EDF, 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   myParent = p;
426 }
427
428 /*!
429   \brief Sets modification state of the object.
430
431   When the object has been modified (modified is set to true)
432   a signal is emitted to notify the tree model and eventually redraw the data object.
433
434   \param modified modified state 
435 */
436 void SUIT_DataObject::setModified(bool modified)
437 {
438   if ( _modified == modified )
439     return;
440
441   _modified = modified;
442   if ( _modified )
443     signal()->emitModified( this );
444 }
445
446 /*!
447   \brief Get data object name.
448
449   This method should be re-implemented in the subclasses.
450   Default implementation returns null string.
451
452   \return object name
453 */
454 QString SUIT_DataObject::name() const
455 {
456   return QString();
457 }
458
459 /*!
460   \brief Get object text data for the specified column.
461
462   This method can be re-implemented in the subclasses.
463   Default implementation returns null string.
464
465   Column with \a id = 0 (NameId) is supposed to be used
466   to get the object name (as it does the default implementation).
467
468   \param id column id
469   \return object text data
470 */
471 QString SUIT_DataObject::text( const int id ) const
472 {
473   return id == NameId ? name() : QString();
474 }
475
476 /*!
477   \brief Get data object icon for the specified column.
478
479   This method can be re-implemented in the subclasses.
480   Default implementation returns null pixmap.
481
482   The parameter \a id specifies the column identificator
483
484   \param id column id
485   \return object icon for the specified column
486 */
487 QPixmap SUIT_DataObject::icon( const int /*id*/ ) const
488 {
489   return QPixmap();
490 }
491
492 /*!
493   \brief Get data object color for the specified column.
494
495   This method can be re-implemented in the subclasses.
496   Default implementation returns null color.
497
498   The parameter \a id specifies the column identificator
499
500   \param role color role
501   \param id column id
502   \return object color for the specified column
503 */
504 QColor SUIT_DataObject::color( const ColorRole /*role*/, const int /*id*/ ) const
505 {
506   return QColor();
507 }
508
509 /*!
510   \brief Get data object tooltip for the specified column.
511
512   This method can be re-implemented in the subclasses.
513   Default implementation returns null string.
514
515   The parameter \a id specifies the column identificator
516   (to display, for example, in the tree view widget).
517
518   \param id column id
519   \return object tooltip for the specified column
520 */
521 QString SUIT_DataObject::toolTip( const int /*id*/ ) const
522 {
523   return QString();
524 }
525
526 /*!
527   \brief Get data object status tip for the specified column.
528
529   This method can be re-implemented in the subclasses.
530   Default implementation returns null string.
531
532   The parameter \a id specifies the column identificator
533
534   \param id column id
535   \return object status tip for the specified column
536 */
537 QString SUIT_DataObject::statusTip( const int /*id*/ ) const
538 {
539   return QString();
540 }
541
542 /*!
543   \brief Get data object "what's this" information for the
544          specified column.
545
546   This method can be re-implemented in the subclasses.
547   Default implementation returns null string.
548
549   The parameter \a id specifies the column identificator
550
551   \param id column id
552   \return object "what's this" information for the specified column
553 */
554 QString SUIT_DataObject::whatsThis( const int /*id*/ ) const
555 {
556   return QString();
557 }
558
559 /*!
560   \brief Get data object font for the specified column.
561
562   This method can be re-implemented in the subclasses.
563   Default implementation returns application default font.
564
565   The parameter \a id specifies the column identificator
566
567   \param id column id
568   \return object font for the specified column
569 */
570 QFont SUIT_DataObject::font( const int /*id*/ ) const
571 {
572   return QFont();
573 }
574
575 /*!
576   \brief Get data object text alignment for the specified column.
577
578   This method can be re-implemented in the subclasses.
579   Default implementation returns default alignment which
580   is Qt:AlignLeft.
581
582   The parameter \a id specifies the column identificator
583   (to display, for example, in the tree view widget).
584
585   \param id column id
586   \return object text alignment flags for the specified column
587 */
588 int SUIT_DataObject::alignment( const int /*id*/ ) const
589 {
590   return Qt::AlignLeft;
591 }
592
593 bool SUIT_DataObject::expandable() const
594 {
595   return true;
596 }
597
598 /*!
599   \brief Check if the object is visible.
600
601   This method can be re-implemented in the subclasses.
602   Default implementation returns \c true (all objects are visible by default).
603
604   \return \c true if this object is displayable or \c false otherwise
605 */
606 bool SUIT_DataObject::isVisible() const
607 {
608   return true;
609 }
610
611 /*!
612   \brief Check if the object is draggable.
613
614   This method can be re-implemented in the subclasses.
615   Default implementation returns \c false (all objects could not be dragged).
616
617   \return \c true if it is possible to drag this object
618 */
619 bool SUIT_DataObject::isDraggable() const
620 {
621   return false;
622 }
623
624 /*!
625   \brief Check if the drop operation for this object is possible.
626
627   This method can be re-implemented in the subclasses.
628   Default implementation returns \c false (drop operation is not allowed).
629
630   \return \c true if it is possible to drop one or more objects (currently selected) to this object
631 */
632 bool SUIT_DataObject::isDropAccepted() const
633 {
634   return false;
635 }
636
637 /*!
638   \brief Check if this object is enabled.
639
640   This method can be re-implemented in the subclasses.
641   Default implementation returns \c true (all objects are enabled).
642
643   \return \c true if the user can interact with the item
644 */
645 bool SUIT_DataObject::isEnabled() const
646 {
647   return true;
648 }
649
650 /*!
651   \brief Check if this object is selectable.
652
653   This method can be re-implemented in the subclasses.
654   Default implementation returns \c true (all objects are selectable).
655
656   \return \c true if the item can be selected
657 */
658 bool SUIT_DataObject::isSelectable() const
659 {
660   return true;
661 }
662
663 /*!
664   \brief Check if this object is checkable for the specified column.
665
666   This method can be re-implemented in the subclasses.
667   Default implementation returns \c false (all objects are not checkable).
668
669   \param id column id
670   \return \c true if the item can be checked or unchecked by the user
671   \sa isOn(), setOn()
672 */
673 bool SUIT_DataObject::isCheckable( const int /*id*/ ) const
674 {
675   return false;
676 }
677
678 /*!
679   \brief Check if this object is can't be renamed in place
680
681   This method can be re-implemented in the subclasses.
682   Default implementation returns \c false (all objects can not be renamed).
683
684   \param id column id
685   \return \c true if the item can be renamed by the user in place (e.g. in the Object browser)
686 */
687 bool SUIT_DataObject::renameAllowed( const int /*id*/ ) const
688 {
689   return false;
690 }
691
692 /*!
693   \brief Set name of the this object.
694
695   This method can be re-implemented in the subclasses.
696   Default implementation returns \c false.
697
698   \return \c true if rename operation finished successfully, \c false otherwise.
699 */
700 bool SUIT_DataObject::setName(const QString& /*name*/) {
701   return false;
702 }
703
704 /*!
705   \brief Get the checked state of the object (if it is checkable)
706   for the specified column.
707
708   Default implementation supports the checked state for the first
709   ("Name") column only.
710
711   \param id column id
712   \return checked state of the object for the specified column
713   \sa setOn(), isCheckable()
714 */
715 bool SUIT_DataObject::isOn( const int id ) const
716 {
717   return id == NameId && myCheck;
718 }
719
720 /*!
721   \brief Set the checked state of the object (if it is checkable)
722   for the specified column.
723
724   Default implementation supports the checked state for the first
725   ("Name") column only.
726
727   \param on new checked state of the object for the specified column
728   \param id column id
729   \sa isOn(), isCheckable()
730 */
731 void SUIT_DataObject::setOn( const bool on, const int id )
732 {
733   if( id == NameId )
734     myCheck = on;
735 }
736
737 /*!
738   \brief Get the "opened" state of the object.
739   \return "opened" state of the object
740   \sa setOpen()
741 */
742 bool SUIT_DataObject::isOpen() const
743 {
744   return myOpen;
745 }
746
747 /*!
748   \brief Set the "opened" state of the object.
749   \param on new "opened" state of the object
750   \sa isOpen()
751 */
752 void SUIT_DataObject::setOpen( const bool on )
753 {
754   myOpen = on;
755 }
756
757 /*!
758   \brief Check if the specified column supports custom sorting.
759
760   This method can be re-implemented in the subclasses.
761   Default implementation returns false ("Name" column does not require
762   custom sorting).
763
764   \param id column id
765   \return \c true if column sorting should be customized
766   \sa compare()
767 */
768 bool SUIT_DataObject::customSorting( const int /*id*/ ) const
769 {
770   return false;
771 }
772
773 /*!
774   \brief Compares data from two items for sorting purposes.
775
776   This method can be re-implemented in the subclasses.
777   Default implementation returns false ("Name" column does not require
778   custom sorting).
779
780   This method is called only for those columns for which customSorting()
781   method returns \c true.
782
783   \param left first data to compare
784   \param right second data to compare
785   \param id column id
786   \return result of the comparison
787   \sa customSorting()
788 */
789 bool SUIT_DataObject::compare( const QVariant& /*left*/, const QVariant& /*right*/,
790                                const int /*id*/ ) const
791 {
792   return false;
793 }
794
795 /*!
796   \brief Get the object unique indentification key.
797
798   This method can be re-implemented in the subclasses.
799   Default implementation returns 0.
800
801   \return object key
802 */
803 SUIT_DataObjectKey* SUIT_DataObject::key() const
804 {
805   return 0;
806 }
807
808 /*!
809   \brief Get global signal handler.
810   \return the only instance of the signal handler
811 */
812 SUIT_DataObject::Signal* SUIT_DataObject::signal()
813 {
814   if ( !mySignal )
815     mySignal = new Signal();
816   return mySignal;
817 }
818
819 /*!
820   \brief Connect to the signal handlerx
821   \param sig signal name
822   \param reciever signal receiver object
823   \param slot slot name
824   \return \c true if connection is successfull
825 */
826 bool SUIT_DataObject::connect( const char* sig, QObject* reciever, const char* slot )
827 {
828   if ( !reciever || !slot )
829     return false;
830
831   signal()->disconnect( signal(), sig, reciever, slot );
832   return signal()->connect( signal(), sig, reciever, slot );
833 }
834
835 /*!
836   \brief Disconnect from the signal handler
837   \param sig signal name
838   \param reciever signal receiver object
839   \param slot slot name
840   \return \c true if disconnection is successfull
841 */
842 bool SUIT_DataObject::disconnect( const char* sig, QObject* reciever, const char* slot )
843 {
844   if ( !reciever || !slot )
845     return false;
846   return signal()->disconnect( signal(), sig, reciever, slot );
847 }
848
849 /*!
850   \brief Schedule this object for the late deleting.
851
852   The object will be deleted when control returns to the event loop.
853   Note that entering and leaving a new event loop (e.g., by opening
854   a modal dialog) will not perform the deferred deletion; for the object
855   to be deleted, the control must return to the event loop from which
856   deleteLater() was called.
857 */
858 void SUIT_DataObject::deleteLater()
859 {
860   if ( parent() )
861     parent()->removeChild( this, false ); // to avoid infinite loop!
862   signal()->deleteLater( this );
863 }
864
865 /*!
866   \brief Dump the object tree recursively to the standard output.
867   \param indent current indentation level
868 */
869 void SUIT_DataObject::dump( const int indent ) const
870 {
871   QString strIndent = QString().fill( ' ', indent ); // indentation string
872   printf( "%s%s\n", strIndent.toLatin1().data(), name().toLatin1().data() );
873   for ( DataObjectList::const_iterator it = myChildren.begin(); it != myChildren.end(); ++it )
874     (*it)->dump( indent + 2 );
875 }
876
877 /*!
878   \class SUIT_DataObject::Signal
879   \brief Watcher class, responsible for the emitting signals on behalf of
880   the data objects.
881
882   SUIT_DataObject class does not inherit from QObject for the performance
883   reasons, so it can not use signals/slots mechanism directly.
884   Instead it uses the only Signal object to emit the signals when the data
885   object is created, destroyed, inserted to the parent object or removed
886   from it.
887
888   If some object needs to handle, for example, data object destroying, it can
889   use SUIT_DataObject::signal() method to connect the signal:
890   \code
891   MyHandler* h = new MyHandler();
892   h->connect( SUIT_DataObject::signal(), SIGNAL(destroyed(SUIT_DataObject*)),
893               h, SLOT(onDestroyed(SUIT_DataObject*)) );
894   \endcode
895   The same can be done by using static method SUIT_DataObject::connect().
896   For example,
897   \code
898   MyHandler* h = new MyHandler();
899   SUIT_DataObject::connect( SIGNAL(destroyed(SUIT_DataObject*)),
900                             h, SLOT(onDestroyed(SUIT_DataObject*)));
901   \endcode
902 */
903
904 /*!
905   \brief Constructor.
906 */
907 SUIT_DataObject::Signal::Signal()
908 : QObject()
909 {
910 }
911
912 /*!
913   \brief Destructor.
914
915   Destroys data object which are scheduled for the deleting with the deleteLater().
916 */
917 SUIT_DataObject::Signal::~Signal()
918 {
919   for ( DataObjectList::Iterator it = myDelLaterObjects.begin();
920         it != myDelLaterObjects.end(); ++it ) {
921     delete *it;
922   }
923   myDelLaterObjects.clear();
924 }
925
926 /*!
927   \brief Emit signal about data object creation.
928   \param object data object being created
929 */
930 void SUIT_DataObject::Signal::emitCreated( SUIT_DataObject* object )
931 {
932   if ( object )
933     emit created( object );
934 }
935
936 /*!
937   \brief Emit signal about data object destroying.
938   \param object data object being destroyed
939 */
940 void SUIT_DataObject::Signal::emitDestroyed( SUIT_DataObject* object )
941 {
942   if ( object ) {
943     if ( myDelLaterObjects.contains( object ) )
944       // object is being destroyed after calling deleteLater():
945       // the signal has been already emitted from deleteLater()
946       // we should avoid repeating of the object destroying from
947       // the Signal destructor
948       myDelLaterObjects.removeAll( object );
949     else
950       // object is being destroyed directly or via deleteLater()
951       emit destroyed( object );
952   }
953 }
954
955 /*!
956   \brief Emit signal about data object adding to the parent data object.
957   \param object data object being added
958   \param parent parent data object
959 */
960 void SUIT_DataObject::Signal::emitInserted( SUIT_DataObject* object, SUIT_DataObject* parent )
961 {
962   emit( inserted( object, parent ) );
963 }
964
965 /*!
966   \brief Emit signal about data object removed from the parent data object.
967   \param object data object being removed
968   \param parent parent data object
969 */
970 void SUIT_DataObject::Signal::emitRemoved( SUIT_DataObject* object, SUIT_DataObject* parent )
971 {
972   emit( removed( object, parent ) );
973 }
974
975 /*!
976   \brief Emit a signal to notify that the data object has been modified.
977   \param object data object that has been modified
978 */
979 void SUIT_DataObject::Signal::emitModified( SUIT_DataObject* object )
980 {
981   emit( modified( object ) );
982 }
983
984 /*!
985   \brief Schedule data object for the late deleting.
986   \param object data object to be deleted later
987 */
988 void SUIT_DataObject::Signal::deleteLater( SUIT_DataObject* object )
989 {
990   if ( !myDelLaterObjects.contains( object ) ) {
991     emitDestroyed( object );
992     myDelLaterObjects.append( object );
993   }
994 }
995
996 /*!
997   \brief Updates necessary internal fields of data object
998 */
999 void SUIT_DataObject::update()
1000 {
1001 }
1002
1003 /*!
1004   \brief return unique group identificator
1005
1006   Groups of data objects are used for column information search.
1007   Each column of data model has one or several registered group id
1008   If object has the same group id as one of registered, the information
1009   will be shown; the custom id of column will be passed into data() method
1010   in order to identify column from point of view of data object
1011
1012  */
1013 int SUIT_DataObject::groupId() const
1014 {
1015   return 0;
1016 }
1017 /*!
1018   \brief return custom data for data object.
1019  */
1020 QVariant SUIT_DataObject::customData(Qtx::CustomDataType /*type*/) {
1021   return QVariant();
1022 }
1023 /*!
1024   \fn void SUIT_DataObject::Signal::created( SUIT_DataObject* object );
1025   \brief Emitted when data object is created.
1026   \param object data object being created
1027 */
1028
1029 /*!
1030   \fn void SUIT_DataObject::Signal::destroyed( SUIT_DataObject* object );
1031   \brief Emitted when data object is destroyed.
1032   \param object data object being destroyed
1033 */
1034
1035 /*!
1036   \fn void SUIT_DataObject::Signal::inserted( SUIT_DataObject* object, SUIT_DataObject* parent );
1037   \brief Emitted when data object is inserted to the parent data object.
1038   \param object data object being created
1039   \param parent parent data object
1040 */
1041
1042 /*!
1043   \fn void SUIT_DataObject::Signal::removed( SUIT_DataObject* object, SUIT_DataObject* parent );
1044   \brief Emitted when data object is removed from the parent data object.
1045   \param object data object being removed
1046   \param parent parent data object
1047 */