1 // Copyright (C) 2007-2012 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
23 // File : SUIT_DataObject.cxx
24 // Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com)
28 #include "SUIT_DataObject.h"
29 #include "SUIT_DataObjectKey.h"
32 SUIT_DataObject::Signal* SUIT_DataObject::mySignal = 0;
35 \class SUIT_DataObject
36 \brief Data object representing the data instance in the tree-like hierarchy.
38 Data object represents uniform data tree structure recommended to use in the
39 SUIT-based applications.
45 Creates the data object with the specified parent.
46 To create the top-level object, pass 0 as parameter.
48 \param p parent object
50 SUIT_DataObject::SUIT_DataObject( SUIT_DataObject* p )
58 signal()->emitCreated( this );
64 Destroys all the children if "auto-delete children" flag is set.
66 SUIT_DataObject::~SUIT_DataObject()
68 SUIT_DataObject* p = myParent;
73 p->removeChild( this );
75 signal()->emitDestroyed( this );
77 for ( DataObjectList::iterator it = myChildren.begin(); it != myChildren.end(); ++it )
80 if ( autoDeleteChildren() )
82 for ( DataObjectList::iterator itr = myChildren.begin(); itr != myChildren.end(); ++itr )
88 \brief Get the root object.
89 \return root object of the data tree
91 SUIT_DataObject* SUIT_DataObject::root() const
93 return parent() ? parent()->root() : (SUIT_DataObject*)this;
97 \brief Get the first child object.
98 \return first child object or 0 if there are no children
101 SUIT_DataObject* SUIT_DataObject::firstChild() const
103 SUIT_DataObject* child = 0;
104 if ( !myChildren.isEmpty() )
105 child = myChildren.first();
110 \brief Get the last child object.
111 \return last child object or 0 if there are no children
114 SUIT_DataObject* SUIT_DataObject::lastChild() const
116 SUIT_DataObject* child = 0;
117 if ( !myChildren.isEmpty() )
118 child = myChildren.last();
123 \brief Get the number of the child objects.
124 \return number of the children
126 int SUIT_DataObject::childCount() const
128 return myChildren.count();
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
136 int SUIT_DataObject::childPos( const SUIT_DataObject* obj ) const
138 return myChildren.indexOf( (SUIT_DataObject*)obj );
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
146 SUIT_DataObject* SUIT_DataObject::childObject( const int idx ) const
148 SUIT_DataObject* child = 0;
150 if ( idx >= 0 && idx < myChildren.count() )
151 child = myChildren.at( idx );
157 \brief Get the object level in the tree structure.
159 Root object has level 0.
161 \return object level.
163 int SUIT_DataObject::level() const
166 SUIT_DataObject* p = parent();
175 \brief Get the position of the data object in its parent's children list
176 \return data object position
178 int SUIT_DataObject::position() const
180 return myParent ? myParent->childPos( this ) : 0;
184 \brief Get the next sibling data object in the children list.
185 \return child object or 0 if there is no next sibling
188 SUIT_DataObject* SUIT_DataObject::nextBrother() const
190 return myParent ? myParent->childObject( myParent->childPos( this ) + 1 ) : 0;
194 \brief Get the previous sibling data object in the children list.
195 \return child object or 0 if there is no previous sibling
198 SUIT_DataObject* SUIT_DataObject::prevBrother() const
200 return myParent ? myParent->childObject( myParent->childPos( this ) - 1 ) : 0;
204 \brief Get "auto-delete children" flag.
205 \return \c true if the object should delete all its children on destroying
206 \sa setAutoDeleteChildren()
208 bool SUIT_DataObject::autoDeleteChildren() const
214 \brief Set "auto-delete children" flag.
216 If this flag is on (default), the object will delete
217 all its children on destroying.
219 \param on new flag value
220 \sa autoDeleteChildren()
222 void SUIT_DataObject::setAutoDeleteChildren( const bool on )
228 \brief Get all children.
230 If parameter \a rec is \c true then function collects all
231 the children recursively.
233 \param lst returning list of children
234 \param rec if \c true collect all children recursively
236 void SUIT_DataObject::children( DataObjectList& lst, const bool rec ) const
238 for ( DataObjectList::const_iterator it = myChildren.begin(); it != myChildren.end(); ++it )
242 (*it)->children( lst, rec );
247 \brief Get all children.
250 If parameter \a rec is \c true then function collects all
251 the children recursively.
253 \param rec if \c true collect all children recursively
254 \return list of children
256 DataObjectList SUIT_DataObject::children( const bool rec )
259 children( lst, rec );
264 \brief Add new child object to the end of the children list.
265 \param obj child object being added
267 void SUIT_DataObject::appendChild( SUIT_DataObject* obj )
269 insertChild( obj, myChildren.count() );
273 \brief Insert new child object to the list of the children.
274 \param obj child object being added
275 \param position child position
277 void SUIT_DataObject::insertChild( SUIT_DataObject* obj, int position )
279 if ( !obj || myChildren.contains( obj ) )
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 );
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
293 void SUIT_DataObject::insertChildAtPos( SUIT_DataObject* obj, int position )
296 int pos = position < 0 ? myChildren.count() : position;
297 myChildren.insert( qMin( pos, (int)myChildren.count() ), obj );
298 obj->assignParent( this );
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
306 void SUIT_DataObject::removeChild( SUIT_DataObject* obj, const bool del )
311 if ( myChildren.removeAll( obj ) ) {
312 signal()->emitRemoved( obj, this );
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
327 bool SUIT_DataObject::replaceChild( SUIT_DataObject* src, SUIT_DataObject* trg, const bool del )
332 int idx = childPos( trg );
335 int pos = childPos( src );
339 insertChild( trg, idx );
343 insertChild( trg, pos );
353 \brief Change the parent for all children from specified object to this one.
354 \param obj object which children to be reparented
356 void SUIT_DataObject::reparentChildren( const SUIT_DataObject* obj )
362 obj->children( lst );
363 for ( DataObjectList::iterator it = lst.begin(); it != lst.end(); ++it )
364 (*it)->setParent( this );
368 \brief Get the parent object.
369 \return parent object or 0 if this is top-level item
371 SUIT_DataObject* SUIT_DataObject::parent() const
377 \brief Change the parent object.
378 \param p new parent object
380 void SUIT_DataObject::setParent( SUIT_DataObject* p )
386 parent()->removeChild( this );
391 parent()->appendChild( this );
394 void SUIT_DataObject::assignParent( SUIT_DataObject* p )
403 \brief Get data object name.
405 This method should be re-implemented in the subclasses.
406 Default implementation returns null string.
410 QString SUIT_DataObject::name() const
416 \brief Get object text data for the specified column.
418 This method can be re-implemented in the subclasses.
419 Default implementation returns null string.
421 Column with \a id = 0 (NameId) is supposed to be used
422 to get the object name (as it does the default implementation).
425 \return object text data
427 QString SUIT_DataObject::text( const int id ) const
429 return id == NameId ? name() : QString();
433 \brief Get data object icon for the specified column.
435 This method can be re-implemented in the subclasses.
436 Default implementation returns null pixmap.
438 The parameter \a id specifies the column identificator
441 \return object icon for the specified column
443 QPixmap SUIT_DataObject::icon( const int /*id*/ ) const
449 \brief Get data object color for the specified column.
451 This method can be re-implemented in the subclasses.
452 Default implementation returns null color.
454 The parameter \a id specifies the column identificator
456 \param role color role
458 \return object color for the specified column
460 QColor SUIT_DataObject::color( const ColorRole /*role*/, const int /*id*/ ) const
466 \brief Get data object tooltip for the specified column.
468 This method can be re-implemented in the subclasses.
469 Default implementation returns null string.
471 The parameter \a id specifies the column identificator
472 (to display, for example, in the tree view widget).
475 \return object tooltip for the specified column
477 QString SUIT_DataObject::toolTip( const int /*id*/ ) const
483 \brief Get data object status tip for the specified column.
485 This method can be re-implemented in the subclasses.
486 Default implementation returns null string.
488 The parameter \a id specifies the column identificator
491 \return object status tip for the specified column
493 QString SUIT_DataObject::statusTip( const int /*id*/ ) const
499 \brief Get data object "what's this" information for the
502 This method can be re-implemented in the subclasses.
503 Default implementation returns null string.
505 The parameter \a id specifies the column identificator
508 \return object "what's this" information for the specified column
510 QString SUIT_DataObject::whatsThis( const int /*id*/ ) const
516 \brief Get data object font for the specified column.
518 This method can be re-implemented in the subclasses.
519 Default implementation returns application default font.
521 The parameter \a id specifies the column identificator
524 \return object font for the specified column
526 QFont SUIT_DataObject::font( const int /*id*/ ) const
532 \brief Get data object text alignment for the specified column.
534 This method can be re-implemented in the subclasses.
535 Default implementation returns default alignment which
538 The parameter \a id specifies the column identificator
539 (to display, for example, in the tree view widget).
542 \return object text alignment flags for the specified column
544 int SUIT_DataObject::alignment( const int /*id*/ ) const
546 return Qt::AlignLeft;
549 bool SUIT_DataObject::expandable() const
555 \brief Check if the object is visible.
557 This method can be re-implemented in the subclasses.
558 Default implementation returns \c true (all objects are visible by default).
560 \return \c true if this object is displayable or \c false otherwise
562 bool SUIT_DataObject::isVisible() const
568 \brief Check if the object is draggable.
570 This method can be re-implemented in the subclasses.
571 Default implementation returns \c false (all objects could not be dragged).
573 \return \c true if it is possible to drag this object
575 bool SUIT_DataObject::isDraggable() const
581 \brief Check if the drop operation for this object is possible.
583 This method can be re-implemented in the subclasses.
584 Default implementation returns \c false (drop operation is not allowed).
586 \return \c true if it is possible to drop one or more objects (currently selected) to this object
588 bool SUIT_DataObject::isDropAccepted() const
594 \brief Check if this object is enabled.
596 This method can be re-implemented in the subclasses.
597 Default implementation returns \c true (all objects are enabled).
599 \return \c true if the user can interact with the item
601 bool SUIT_DataObject::isEnabled() const
607 \brief Check if this object is selectable.
609 This method can be re-implemented in the subclasses.
610 Default implementation returns \c true (all objects are selectable).
612 \return \c true if the item can be selected
614 bool SUIT_DataObject::isSelectable() const
620 \brief Check if this object is checkable for the specified column.
622 This method can be re-implemented in the subclasses.
623 Default implementation returns \c false (all objects are not checkable).
626 \return \c true if the item can be checked or unchecked by the user
629 bool SUIT_DataObject::isCheckable( const int /*id*/ ) const
635 \brief Check if this object is can't be renamed in place
637 This method can be re-implemented in the subclasses.
638 Default implementation returns \c false (all objects can not be renamed).
641 \return \c true if the item can be renamed by the user in place (e.g. in the Object browser)
643 bool SUIT_DataObject::renameAllowed( const int /*id*/ ) const
649 \brief Set name of the this object.
651 This method can be re-implemented in the subclasses.
652 Default implementation returns \c false.
654 \return \c true if rename operation finished successfully, \c false otherwise.
656 bool SUIT_DataObject::setName(const QString& /*name*/) {
661 \brief Get the checked state of the object (if it is checkable)
662 for the specified column.
664 Default implementation supports the checked state for the first
665 ("Name") column only.
668 \return checked state of the object for the specified column
669 \sa setOn(), isCheckable()
671 bool SUIT_DataObject::isOn( const int id ) const
673 return id == NameId && myCheck;
677 \brief Set the checked state of the object (if it is checkable)
678 for the specified column.
680 Default implementation supports the checked state for the first
681 ("Name") column only.
683 \param on new checked state of the object for the specified column
685 \sa isOn(), isCheckable()
687 void SUIT_DataObject::setOn( const bool on, const int id )
694 \brief Get the "opened" state of the object.
695 \return "opened" state of the object
698 bool SUIT_DataObject::isOpen() const
704 \brief Set the "opened" state of the object.
705 \param on new "opened" state of the object
708 void SUIT_DataObject::setOpen( const bool on )
714 \brief Check if the specified column supports custom sorting.
716 This method can be re-implemented in the subclasses.
717 Default implementation returns false ("Name" column does not require
721 \return \c true if column sorting should be customized
724 bool SUIT_DataObject::customSorting( const int /*id*/ ) const
730 \brief Compares data from two items for sorting purposes.
732 This method can be re-implemented in the subclasses.
733 Default implementation returns false ("Name" column does not require
736 This method is called only for those columns for which customSorting()
737 method returns \c true.
739 \param left first data to compare
740 \param right second data to compare
742 \return result of the comparison
745 bool SUIT_DataObject::compare( const QVariant& /*left*/, const QVariant& /*right*/,
746 const int /*id*/ ) const
752 \brief Get the object unique indentification key.
754 This method can be re-implemented in the subclasses.
755 Default implementation returns 0.
759 SUIT_DataObjectKey* SUIT_DataObject::key() const
765 \brief Get global signal handler.
766 \return the only instance of the signal handler
768 SUIT_DataObject::Signal* SUIT_DataObject::signal()
771 mySignal = new Signal();
776 \brief Connect to the signal handlerx
777 \param sig signal name
778 \param reciever signal receiver object
779 \param slot slot name
780 \return \c true if connection is successfull
782 bool SUIT_DataObject::connect( const char* sig, QObject* reciever, const char* slot )
784 if ( !reciever || !slot )
787 signal()->disconnect( signal(), sig, reciever, slot );
788 return signal()->connect( signal(), sig, reciever, slot );
792 \brief Disconnect from the signal handler
793 \param sig signal name
794 \param reciever signal receiver object
795 \param slot slot name
796 \return \c true if disconnection is successfull
798 bool SUIT_DataObject::disconnect( const char* sig, QObject* reciever, const char* slot )
800 if ( !reciever || !slot )
802 return signal()->disconnect( signal(), sig, reciever, slot );
806 \brief Schedule this object for the late deleting.
808 The object will be deleted when control returns to the event loop.
809 Note that entering and leaving a new event loop (e.g., by opening
810 a modal dialog) will not perform the deferred deletion; for the object
811 to be deleted, the control must return to the event loop from which
812 deleteLater() was called.
814 void SUIT_DataObject::deleteLater()
817 parent()->removeChild( this, false ); // to avoid infinite loop!
818 signal()->deleteLater( this );
822 \brief Dump the object tree recursively to the standard output.
823 \param indent current indentation level
825 void SUIT_DataObject::dump( const int indent ) const
827 QString strIndent = QString().fill( ' ', indent ); // indentation string
828 printf( "%s%s\n", strIndent.toLatin1().data(), name().toLatin1().data() );
829 for ( DataObjectList::const_iterator it = myChildren.begin(); it != myChildren.end(); ++it )
830 (*it)->dump( indent + 2 );
834 \class SUIT_DataObject::Signal
835 \brief Watcher class, responsible for the emitting signals on behalf of
838 SUIT_DataObject class does not inherit from QObject for the performance
839 reasons, so it can not use signals/slots mechanism directly.
840 Instead it uses the only Signal object to emit the signals when the data
841 object is created, destroyed, inserted to the parent object or removed
844 If some object needs to handle, for example, data object destroying, it can
845 use SUIT_DataObject::signal() method to connect the signal:
847 MyHandler* h = new MyHandler();
848 h->connect( SUIT_DataObject::signal(), SIGNAL(destroyed(SUIT_DataObject*)),
849 h, SLOT(onDestroyed(SUIT_DataObject*)) );
851 The same can be done by using static method SUIT_DataObject::connect().
854 MyHandler* h = new MyHandler();
855 SUIT_DataObject::connect( SIGNAL(destroyed(SUIT_DataObject*)),
856 h, SLOT(onDestroyed(SUIT_DataObject*)));
863 SUIT_DataObject::Signal::Signal()
871 Destroys data object which are scheduled for the deleting with the deleteLater().
873 SUIT_DataObject::Signal::~Signal()
875 for ( DataObjectList::Iterator it = myDelLaterObjects.begin();
876 it != myDelLaterObjects.end(); ++it ) {
879 myDelLaterObjects.clear();
883 \brief Emit signal about data object creation.
884 \param object data object being created
886 void SUIT_DataObject::Signal::emitCreated( SUIT_DataObject* object )
889 emit created( object );
893 \brief Emit signal about data object destroying.
894 \param object data object being destroyed
896 void SUIT_DataObject::Signal::emitDestroyed( SUIT_DataObject* object )
899 if ( myDelLaterObjects.contains( object ) )
900 // object is being destroyed after calling deleteLater():
901 // the signal has been already emitted from deleteLater()
902 // we should avoid repeating of the object destroying from
903 // the Signal destructor
904 myDelLaterObjects.removeAll( object );
906 // object is being destroyed directly or via deleteLater()
907 emit destroyed( object );
912 \brief Emit signal about data object adding to the parent data object.
913 \param object data object being added
914 \param parent parent data object
916 void SUIT_DataObject::Signal::emitInserted( SUIT_DataObject* object, SUIT_DataObject* parent )
918 emit( inserted( object, parent ) );
922 \brief Emit signal about data object removed from the parent data object.
923 \param object data object being removed
924 \param parent parent data object
926 void SUIT_DataObject::Signal::emitRemoved( SUIT_DataObject* object, SUIT_DataObject* parent )
928 emit( removed( object, parent ) );
932 \brief Schedule data object for the late deleting.
933 \param object data object to be deleted later
935 void SUIT_DataObject::Signal::deleteLater( SUIT_DataObject* object )
937 if ( !myDelLaterObjects.contains( object ) ) {
938 emitDestroyed( object );
939 myDelLaterObjects.append( object );
944 \brief Updates necessary internal fields of data object
946 void SUIT_DataObject::update()
951 \brief return unique group identificator
953 Groups of data objects are used for column information search.
954 Each column of data model has one or several registered group id
955 If object has the same group id as one of registered, the information
956 will be shown; the custom id of column will be passed into data() method
957 in order to identify column from point of view of data object
960 int SUIT_DataObject::groupId() const
965 \brief return custom data for data object.
967 QVariant SUIT_DataObject::customData(Qtx::CustomDataType /*type*/) {
971 \fn void SUIT_DataObject::Signal::created( SUIT_DataObject* object );
972 \brief Emitted when data object is created.
973 \param object data object being created
977 \fn void SUIT_DataObject::Signal::destroyed( SUIT_DataObject* object );
978 \brief Emitted when data object is destroyed.
979 \param object data object being destroyed
983 \fn void SUIT_DataObject::Signal::inserted( SUIT_DataObject* object, SUIT_DataObject* parent );
984 \brief Emitted when data object is inserted to the parent data object.
985 \param object data object being created
986 \param parent parent data object
990 \fn void SUIT_DataObject::Signal::removed( SUIT_DataObject* object, SUIT_DataObject* parent );
991 \brief Emitted when data object is removed from the parent data object.
992 \param object data object being removed
993 \param parent parent data object