1 // Copyright (C) 2007-2008 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
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.
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.
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
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
22 // File : SUIT_DataObject.cxx
23 // Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com)
25 #include "SUIT_DataObject.h"
26 #include "SUIT_DataObjectKey.h"
28 SUIT_DataObject::Signal* SUIT_DataObject::mySignal = 0;
31 \class SUIT_DataObject
32 \brief Data object representing the data instance in the tree-like hierarchy.
34 Data object represents uniform data tree structure recommended to use in the
35 SUIT-based applications.
41 Creates the data object with the specified parent.
42 To create the top-level object, pass 0 as parameter.
44 \param p parent object
46 SUIT_DataObject::SUIT_DataObject( SUIT_DataObject* p )
53 signal()->emitCreated( this );
59 Destroys all the children if "auto-delete children" flag is set.
61 SUIT_DataObject::~SUIT_DataObject()
63 SUIT_DataObject* p = myParent;
68 p->removeChild( this );
70 signal()->emitDestroyed( this );
72 for ( DataObjectList::iterator it = myChildren.begin(); it != myChildren.end(); ++it )
75 if ( autoDeleteChildren() )
77 for ( DataObjectList::iterator itr = myChildren.begin(); itr != myChildren.end(); ++itr )
83 \brief Get the root object.
84 \return root object of the data tree
86 SUIT_DataObject* SUIT_DataObject::root() const
88 return parent() ? parent()->root() : (SUIT_DataObject*)this;
92 \brief Get the first child object.
93 \return first child object or 0 if there are no children
96 SUIT_DataObject* SUIT_DataObject::firstChild() const
98 SUIT_DataObject* child = 0;
99 if ( !myChildren.isEmpty() )
100 child = myChildren.first();
105 \brief Get the last child object.
106 \return last child object or 0 if there are no children
109 SUIT_DataObject* SUIT_DataObject::lastChild() const
111 SUIT_DataObject* child = 0;
112 if ( !myChildren.isEmpty() )
113 child = myChildren.last();
118 \brief Get the number of the child objects.
119 \return number of the children
121 int SUIT_DataObject::childCount() const
123 return myChildren.count();
127 \brief Get the index of the specified object in the child list.
128 \param obj child object
129 \return subobject position or -1 if it does not belong to this object
131 int SUIT_DataObject::childPos( const SUIT_DataObject* obj ) const
133 return myChildren.indexOf( (SUIT_DataObject*)obj );
137 \brief Get child object by the specified index.
138 \param idx child object index
139 \return child object or 0 if index is out of range
141 SUIT_DataObject* SUIT_DataObject::childObject( const int idx ) const
143 SUIT_DataObject* child = 0;
145 if ( idx >= 0 && idx < myChildren.count() )
146 child = myChildren.at( idx );
152 \brief Get the object level in the tree structure.
154 Root object has level 0.
156 \return object level.
158 int SUIT_DataObject::level() const
161 SUIT_DataObject* p = parent();
170 \brief Get the position of the data object in its parent's children list
171 \return data object position
173 int SUIT_DataObject::position() const
175 return myParent ? myParent->childPos( this ) : 0;
179 \brief Get the next sibling data object in the children list.
180 \return child object or 0 if there is no next sibling
183 SUIT_DataObject* SUIT_DataObject::nextBrother() const
185 return myParent ? myParent->childObject( myParent->childPos( this ) + 1 ) : 0;
189 \brief Get the previous sibling data object in the children list.
190 \return child object or 0 if there is no previous sibling
193 SUIT_DataObject* SUIT_DataObject::prevBrother() const
195 return myParent ? myParent->childObject( myParent->childPos( this ) - 1 ) : 0;
199 \brief Get "auto-delete children" flag.
200 \return \c true if the object should delete all its children on destroying
201 \sa setAutoDeleteChildren()
203 bool SUIT_DataObject::autoDeleteChildren() const
209 \brief Set "auto-delete children" flag.
211 If this flag is on (default), the object will delete
212 all its children on destroying.
214 \param on new flag value
215 \sa autoDeleteChildren()
217 void SUIT_DataObject::setAutoDeleteChildren( const bool on )
223 \brief Get all children.
225 If parameter \a rec is \c true then function collects all
226 the children recursively.
228 \param lst returning list of children
229 \param rec if \c true collect all children recursively
231 void SUIT_DataObject::children( DataObjectList& lst, const bool rec ) const
233 for ( DataObjectList::const_iterator it = myChildren.begin(); it != myChildren.end(); ++it )
237 (*it)->children( lst, rec );
242 \brief Get all children.
245 If parameter \a rec is \c true then function collects all
246 the children recursively.
248 \param rec if \c true collect all children recursively
249 \return list of children
251 DataObjectList SUIT_DataObject::children( const bool rec )
254 children( lst, rec );
259 \brief Add new child object to the end of the children list.
260 \param obj child object being added
262 void SUIT_DataObject::appendChild( SUIT_DataObject* obj )
264 insertChild( obj, myChildren.count() );
268 \brief Insert new child object to the list of the children.
269 \param obj child object being added
270 \param position child position
272 void SUIT_DataObject::insertChild( SUIT_DataObject* obj, int position )
274 if ( !obj || myChildren.contains( obj ) )
277 int pos = position < 0 ? myChildren.count() : position;
278 myChildren.insert( qMin( pos, (int)myChildren.count() ), obj );
279 obj->setParent( this );
280 signal()->emitInserted( obj, this );
284 \brief Remove the specified child object reference.
285 \param obj child object being removed
286 \param del if \c true, the child object is destroyed
288 void SUIT_DataObject::removeChild( SUIT_DataObject* obj, const bool del )
293 if ( myChildren.removeAll( obj ) ) {
294 signal()->emitRemoved( obj, this );
303 \brief Replace the specified child object by another object.
304 \param src child object being replaced
305 \param trg new child object
306 \param del if \c true, the previous object is destroyed
307 \return \c true if the object has been replaced
309 bool SUIT_DataObject::replaceChild( SUIT_DataObject* src, SUIT_DataObject* trg, const bool del )
314 int idx = childPos( trg );
317 int pos = childPos( src );
321 insertChild( trg, idx );
325 insertChild( trg, pos );
335 \brief Change the parent for all children from specified object to this one.
336 \param obj object which children to be reparented
338 void SUIT_DataObject::reparentChildren( const SUIT_DataObject* obj )
344 obj->children( lst );
345 for ( DataObjectList::iterator it = lst.begin(); it != lst.end(); ++it )
346 (*it)->setParent( this );
350 \brief Get the parent object.
351 \return parent object or 0 if this is top-level item
353 SUIT_DataObject* SUIT_DataObject::parent() const
359 \brief Change the parent object.
360 \param p new parent object
362 void SUIT_DataObject::setParent( SUIT_DataObject* p )
368 parent()->removeChild( this );
373 parent()->appendChild( this );
377 \brief Get data object name.
379 This method should be re-implemented in the subclasses.
380 Default implementation returns null string.
384 QString SUIT_DataObject::name() const
390 \brief Get object text data for the specified column.
392 This method can be re-implemented in the subclasses.
393 Default implementation returns null string.
395 Column with \a id = 0 (NameId) is supposed to be used
396 to get the object name (as it does the default implementation).
399 \return object text data
401 QString SUIT_DataObject::text( const int id ) const
403 return id == NameId ? name() : QString();
407 \brief Get data object icon for the specified column.
409 This method can be re-implemented in the subclasses.
410 Default implementation returns null pixmap.
412 The parameter \a id specifies the column identificator
415 \return object icon for the specified column
417 QPixmap SUIT_DataObject::icon( const int /*id*/ ) const
423 \brief Get data object color for the specified column.
425 This method can be re-implemented in the subclasses.
426 Default implementation returns null color.
428 The parameter \a id specifies the column identificator
430 \param role color role
432 \return object color for the specified column
434 QColor SUIT_DataObject::color( const ColorRole /*role*/, const int /*id*/ ) const
440 \brief Get data object tooltip for the specified column.
442 This method can be re-implemented in the subclasses.
443 Default implementation returns null string.
445 The parameter \a id specifies the column identificator
446 (to display, for example, in the tree view widget).
449 \return object tooltip for the specified column
451 QString SUIT_DataObject::toolTip( const int /*id*/ ) const
457 \brief Get data object status tip for the specified column.
459 This method can be re-implemented in the subclasses.
460 Default implementation returns null string.
462 The parameter \a id specifies the column identificator
465 \return object status tip for the specified column
467 QString SUIT_DataObject::statusTip( const int /*id*/ ) const
473 \brief Get data object "what's this" information for the
476 This method can be re-implemented in the subclasses.
477 Default implementation returns null string.
479 The parameter \a id specifies the column identificator
482 \return object "what's this" information for the specified column
484 QString SUIT_DataObject::whatsThis( const int /*id*/ ) const
490 \brief Get data object font for the specified column.
492 This method can be re-implemented in the subclasses.
493 Default implementation returns application default font.
495 The parameter \a id specifies the column identificator
498 \return object font for the specified column
500 QFont SUIT_DataObject::font( const int /*id*/ ) const
506 \brief Get data object text alignment for the specified column.
508 This method can be re-implemented in the subclasses.
509 Default implementation returns default alignment which
512 The parameter \a id specifies the column identificator
513 (to display, for example, in the tree view widget).
516 \return object text alignment flags for the specified column
518 int SUIT_DataObject::alignment( const int /*id*/ ) const
520 return Qt::AlignLeft;
524 \brief Check if the object is draggable.
526 This method can be re-implemented in the subclasses.
527 Default implementation returns \c false (all objects could not be dragged).
529 \return \c true if it is possible to drag this object
531 bool SUIT_DataObject::isDragable() const
537 \brief Check if the drop operation fo this object is possible.
539 This method can be re-implemented in the subclasses.
540 Default implementation returns \c false (drop operation is not allowed).
542 \param obj object being dropped
543 \return \c true if it is possible to drop an object \c obj
547 bool SUIT_DataObject::isDropAccepted( SUIT_DataObject* /*obj*/ )
553 \brief Check if this object is enabled.
555 This method can be re-implemented in the subclasses.
556 Default implementation returns \c true (all objects are enabled).
558 \return \c true if the user can interact with the item
560 bool SUIT_DataObject::isEnabled() const
566 \brief Check if this object is selectable.
568 This method can be re-implemented in the subclasses.
569 Default implementation returns \c true (all objects are selectable).
571 \return \c true if the item can be selected
573 bool SUIT_DataObject::isSelectable() const
579 \brief Check if this object is checkable for the specified column.
581 This method can be re-implemented in the subclasses.
582 Default implementation returns \c false (all objects are not checkable).
585 \return \c true if the item can be checked or unchecked by the user
588 bool SUIT_DataObject::isCheckable( const int /*id*/ ) const
594 \brief Get the checked state of the object (if it is checkable)
595 for the specified column.
597 Default implementation supports the checked state for the first
598 ("Name") column only.
601 \return checked state of the object for the specified column
602 \sa setOn(), isCheckable()
604 bool SUIT_DataObject::isOn( const int id ) const
606 return id == NameId && myCheck;
610 \brief Set the checked state of the object (if it is checkable)
611 for the specified column.
613 Default implementation supports the checked state for the first
614 ("Name") column only.
616 \param on new checked state of the object for the specified column
618 \sa isOn(), isCheckable()
620 void SUIT_DataObject::setOn( const bool on, const int id )
627 \brief Get the "opened" state of the object.
628 \return "opened" state of the object
631 bool SUIT_DataObject::isOpen() const
637 \brief Set the "opened" state of the object.
638 \param on new "opened" state of the object
641 void SUIT_DataObject::setOpen( const bool on )
647 \brief Check if the specified column supports custom sorting.
649 This method can be re-implemented in the subclasses.
650 Default implementation returns false ("Name" column does not require
654 \return \c true if column sorting should be customized
657 bool SUIT_DataObject::customSorting( const int /*id*/ ) const
663 \brief Compares data from two items for sorting purposes.
665 This method can be re-implemented in the subclasses.
666 Default implementation returns false ("Name" column does not require
669 This method is called only for those columns for which customSorting()
670 method returns \c true.
672 \param left first data to compare
673 \param right second data to compare
675 \return result of the comparison
678 bool SUIT_DataObject::compare( const QVariant& /*left*/, const QVariant& /*right*/,
679 const int /*id*/ ) const
685 \brief Get the object unique indentification key.
687 This method can be re-implemented in the subclasses.
688 Default implementation returns 0.
692 SUIT_DataObjectKey* SUIT_DataObject::key() const
698 \brief Get global signal handler.
699 \return the only instance of the signal handler
701 SUIT_DataObject::Signal* SUIT_DataObject::signal()
704 mySignal = new Signal();
709 \brief Connect to the signal handlerx
710 \param sig signal name
711 \param reciever signal receiver object
712 \param slot slot name
713 \return \c true if connection is successfull
715 bool SUIT_DataObject::connect( const char* sig, QObject* reciever, const char* slot )
717 if ( !reciever || !slot )
720 signal()->disconnect( signal(), sig, reciever, slot );
721 return signal()->connect( signal(), sig, reciever, slot );
725 \brief Disconnect from the signal handler
726 \param sig signal name
727 \param reciever signal receiver object
728 \param slot slot name
729 \return \c true if disconnection is successfull
731 bool SUIT_DataObject::disconnect( const char* sig, QObject* reciever, const char* slot )
733 if ( !reciever || !slot )
735 return signal()->disconnect( signal(), sig, reciever, slot );
739 \brief Schedule this object for the late deleting.
741 The object will be deleted when control returns to the event loop.
742 Note that entering and leaving a new event loop (e.g., by opening
743 a modal dialog) will not perform the deferred deletion; for the object
744 to be deleted, the control must return to the event loop from which
745 deleteLater() was called.
747 void SUIT_DataObject::deleteLater()
750 parent()->removeChild( this, false ); // to avoid infinite loop!
751 signal()->deleteLater( this );
755 \brief Dump the object tree recursively to the standard output.
756 \param indent current indentation level
758 void SUIT_DataObject::dump( const int indent ) const
760 QString strIndent = QString().fill( ' ', indent ); // indentation string
761 printf( "%s%s\n", strIndent.toLatin1().data(), name().toLatin1().data() );
762 for ( DataObjectList::const_iterator it = myChildren.begin(); it != myChildren.end(); ++it )
763 (*it)->dump( indent + 2 );
767 \class SUIT_DataObject::Signal
768 \brief Watcher class, responsible for the emitting signals on behalf of
771 SUIT_DataObject class does not inherit from QObject for the performance
772 reasons, so it can not use signals/slots mechanism directly.
773 Instead it uses the only Signal object to emit the signals when the data
774 object is created, destroyed, inserted to the parent object or removed
777 If some object needs to handle, for example, data object destroying, it can
778 use SUIT_DataObject::signal() method to connect the signal:
780 MyHandler* h = new MyHandler();
781 h->connect( SUIT_DataObject::signal(), SIGNAL(destroyed(SUIT_DataObject*)),
782 h, SLOT(onDestroyed(SUIT_DataObject*)) );
784 The same can be done by using static method SUIT_DataObject::connect().
787 MyHandler* h = new MyHandler();
788 SUIT_DataObject::connect( SIGNAL(destroyed(SUIT_DataObject*)),
789 h, SLOT(onDestroyed(SUIT_DataObject*)));
796 SUIT_DataObject::Signal::Signal()
804 Destroys data object which are scheduled for the deleting with the deleteLater().
806 SUIT_DataObject::Signal::~Signal()
808 for ( DataObjectList::Iterator it = myDelLaterObjects.begin();
809 it != myDelLaterObjects.end(); ++it ) {
812 myDelLaterObjects.clear();
816 \brief Emit signal about data object creation.
817 \param object data object being created
819 void SUIT_DataObject::Signal::emitCreated( SUIT_DataObject* object )
822 emit created( object );
826 \brief Emit signal about data object destroying.
827 \param object data object being destroyed
829 void SUIT_DataObject::Signal::emitDestroyed( SUIT_DataObject* object )
832 if ( myDelLaterObjects.contains( object ) )
833 // object is being destroyed after calling deleteLater():
834 // the signal has been already emitted from deleteLater()
835 // we should avoid repeating of the object destroying from
836 // the Signal destructor
837 myDelLaterObjects.removeAll( object );
839 // object is being destroyed directly or via deleteLater()
840 emit destroyed( object );
845 \brief Emit signal about data object adding to the parent data object.
846 \param object data object being added
847 \param parent parent data object
849 void SUIT_DataObject::Signal::emitInserted( SUIT_DataObject* object, SUIT_DataObject* parent )
851 emit( inserted( object, parent ) );
855 \brief Emit signal about data object removed from the parent data object.
856 \param object data object being removed
857 \param parent parent data object
859 void SUIT_DataObject::Signal::emitRemoved( SUIT_DataObject* object, SUIT_DataObject* parent )
861 emit( removed( object, parent ) );
865 \brief Schedule data object for the late deleting.
866 \param object data object to be deleted later
868 void SUIT_DataObject::Signal::deleteLater( SUIT_DataObject* object )
870 if ( !myDelLaterObjects.contains( object ) ) {
871 emitDestroyed( object );
872 myDelLaterObjects.append( object );
877 \brief Updates necessary internal fields of data object
879 void SUIT_DataObject::update()
884 \brief return unique group identificator
886 Groups of data objects are used for column information search.
887 Each column of data model has one or several registered group id
888 If object has the same group id as one of registered, the information
889 will be shown; the custom id of column will be passed into data() method
890 in order to identify column from point of view of data object
893 int SUIT_DataObject::groupId() const
899 \fn void SUIT_DataObject::Signal::created( SUIT_DataObject* object );
900 \brief Emitted when data object is created.
901 \param object data object being created
905 \fn void SUIT_DataObject::Signal::destroyed( SUIT_DataObject* object );
906 \brief Emitted when data object is destroyed.
907 \param object data object being destroyed
911 \fn void SUIT_DataObject::Signal::inserted( SUIT_DataObject* object, SUIT_DataObject* parent );
912 \brief Emitted when data object is inserted to the parent data object.
913 \param object data object being created
914 \param parent parent data object
918 \fn void SUIT_DataObject::Signal::removed( SUIT_DataObject* object, SUIT_DataObject* parent );
919 \brief Emitted when data object is removed from the parent data object.
920 \param object data object being removed
921 \param parent parent data object