X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FSUIT%2FSUIT_DataObject.cxx;h=aef7afdbb28cd54b0793563ed951c06efc19fafd;hb=refs%2Ftags%2FV9_11_0;hp=1082579fc137817c41e73b3aab5100de6ca489e5;hpb=399155730966dfc225fbb24f66204b05664385f2;p=modules%2Fgui.git diff --git a/src/SUIT/SUIT_DataObject.cxx b/src/SUIT/SUIT_DataObject.cxx old mode 100755 new mode 100644 index 1082579fc..aef7afdbb --- a/src/SUIT/SUIT_DataObject.cxx +++ b/src/SUIT/SUIT_DataObject.cxx @@ -1,46 +1,68 @@ -// Copyright (C) 2005 OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D -// +// Copyright (C) 2007-2023 CEA, EDF, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License. -// -// This library is distributed in the hope that it will be useful -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // -#include "SUIT_DataObject.h" -#include +// File : SUIT_DataObject.cxx +// Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com) + +#include +#include "SUIT_DataObject.h" #include "SUIT_DataObjectKey.h" +#include + +SUIT_DataObject::Signal* SUIT_DataObject::mySignal = 0; /*! - Constructor + \class SUIT_DataObject + \brief Data object representing the data instance in the tree-like hierarchy. + + Data object represents uniform data tree structure recommended to use in the + SUIT-based applications. */ +/*! + \brief Constructor. + + Creates the data object with the specified parent. + To create the top-level object, pass 0 as parameter. + + \param p parent object +*/ SUIT_DataObject::SUIT_DataObject( SUIT_DataObject* p ) : myParent( 0 ), - mySignal( 0 ), myOpen( false ), - myCheck( false ) + myCheck( false ), + myAutoDel( true ), + _modified( false ) { - myChildren.setAutoDelete( true ); - setParent( p ); + signal()->emitCreated( this ); } /*! - Destructor -*/ + \brief Destructor. + Destroys all the children if "auto-delete children" flag is set. +*/ SUIT_DataObject::~SUIT_DataObject() { SUIT_DataObject* p = myParent; @@ -50,100 +72,113 @@ SUIT_DataObject::~SUIT_DataObject() if ( p ) p->removeChild( this ); - if ( mySignal ) - { - mySignal->emitSignal(); - mySignal->setOwner( 0 ); - } + signal()->emitDestroyed( this ); - for ( QPtrListIterator it( myChildren ); it.current(); ++it ) - it.current()->myParent = 0; + for ( DataObjectList::iterator it = myChildren.begin(); it != myChildren.end(); ++it ) + (*it)->myParent = 0; - delete mySignal; + if ( autoDeleteChildren() ) + { + for ( DataObjectList::iterator itr = myChildren.begin(); itr != myChildren.end(); ++itr ) + delete *itr; + } } /*! - Returns the root object. + \brief Get the root object. + \return root object of the data tree */ - SUIT_DataObject* SUIT_DataObject::root() const { return parent() ? parent()->root() : (SUIT_DataObject*)this; } /*! - Returns the first child object. + \brief Get the first child object. + \return first child object or 0 if there are no children + \sa lastChild() */ - SUIT_DataObject* SUIT_DataObject::firstChild() const { SUIT_DataObject* child = 0; if ( !myChildren.isEmpty() ) - child = myChildren.getFirst(); + child = myChildren.first(); return child; } /*! - Returns the last child object. + \brief Get the last child object. + \return last child object or 0 if there are no children + \sa firstChild() */ - SUIT_DataObject* SUIT_DataObject::lastChild() const { SUIT_DataObject* child = 0; if ( !myChildren.isEmpty() ) - child = myChildren.getLast(); + child = myChildren.last(); return child; } /*! - Returns the number of the child objects. + \brief Get the number of the child objects. + \return number of the children */ - int SUIT_DataObject::childCount() const { return myChildren.count(); } /*! - Returns the index of the specified object in the child list or -1. + \brief Get the index of the specified object in the child list. + \param obj child object + \return subobject position or -1 if it does not belong to this object */ - int SUIT_DataObject::childPos( const SUIT_DataObject* obj ) const { - int res = -1; + return myChildren.indexOf( (SUIT_DataObject*)obj ); +} - int i = 0; - for ( DataObjectListIterator it( myChildren ); it.current() && res == -1; ++it, i++ ) - { - if ( it.current() == obj ) - res = i; - } +/*! + \brief Moves the child position from current to new one. + \param theObj child object + \param theNewPos child objectnew position in the children list + +*/ +void SUIT_DataObject::moveChildPos( SUIT_DataObject* theObj, int theNewPos) +{ + if (myChildren.size() <= 1) return; + + int aNewPos = theNewPos; + if (aNewPos < 0) aNewPos = 0; + if (aNewPos > (myChildren.size() - 1)) aNewPos = myChildren.size() - 1; - return res; + if (myChildren.removeOne(theObj)) + myChildren.insert(aNewPos, theObj); } + /*! - Returns the child object with specified index. + \brief Get child object by the specified index. + \param idx child object index + \return child object or 0 if index is out of range */ - SUIT_DataObject* SUIT_DataObject::childObject( const int idx ) const { SUIT_DataObject* child = 0; - if ( idx>= 0 && idx < (int)myChildren.count() ) - { - SUIT_DataObject* that = (SUIT_DataObject*)this; - child = that->myChildren.at( idx ); - } + if ( idx >= 0 && idx < myChildren.count() ) + child = myChildren.at( idx ); return child; } /*! - Returns the level of the object in the data tree. - 0 means that object is top-level. -*/ + \brief Get the object level in the tree structure. + + Root object has level 0. + \return object level. +*/ int SUIT_DataObject::level() const { int lev = 0; @@ -156,59 +191,97 @@ int SUIT_DataObject::level() const } /*! - Returns the next data object in the child list of the parent. + \brief Get the position of the data object in its parent's children list + \return data object position */ +int SUIT_DataObject::position() const +{ + return myParent ? myParent->childPos( this ) : 0; +} + +/*! + \brief Sets new position of the object in parent's list +*/ +void SUIT_DataObject::setPosition(int theNewPos) +{ + if (theNewPos == position()) return; + if (!myParent) return; + myParent->moveChildPos(this, theNewPos); +} +/*! + \brief Get the next sibling data object in the children list. + \return child object or 0 if there is no next sibling + \sa prevBrother() +*/ SUIT_DataObject* SUIT_DataObject::nextBrother() const { return myParent ? myParent->childObject( myParent->childPos( this ) + 1 ) : 0; } /*! - Returns the previous data object in the child list of the parent. + \brief Get the previous sibling data object in the children list. + \return child object or 0 if there is no previous sibling + \sa nextBrother() */ - SUIT_DataObject* SUIT_DataObject::prevBrother() const { return myParent ? myParent->childObject( myParent->childPos( this ) - 1 ) : 0; } /*! - Returns 'true' if the object will delete children during destroying + \brief Get "auto-delete children" flag. + \return \c true if the object should delete all its children on destroying + \sa setAutoDeleteChildren() */ - bool SUIT_DataObject::autoDeleteChildren() const { - return myChildren.autoDelete(); + return myAutoDel; } /*! - Specify should the object delete children during destroying -*/ + \brief Set "auto-delete children" flag. + + If this flag is on (default), the object will delete + all its children on destroying. + \param on new flag value + \sa autoDeleteChildren() +*/ void SUIT_DataObject::setAutoDeleteChildren( const bool on ) { - myChildren.setAutoDelete( on ); + myAutoDel = on; } /*! - Returns the list of the child objects. if 'rec' is 'true' then function get all sub children. -*/ + \brief Get all children. + If parameter \a rec is \c true then function collects all + the children recursively. + + \param lst returning list of children + \param rec if \c true collect all children recursively +*/ void SUIT_DataObject::children( DataObjectList& lst, const bool rec ) const { - for ( DataObjectListIterator it( myChildren ); it.current(); ++it ) + for ( DataObjectList::const_iterator it = myChildren.begin(); it != myChildren.end(); ++it ) { - lst.append( it.current() ); + lst.append( *it ); if ( rec ) - it.current()->children( lst, rec ); + (*it)->children( lst, rec ); } } /*! - Returns the list of the child objects. if 'rec' is 'true' then function get all sub children. -*/ + \brief Get all children. + \override + If parameter \a rec is \c true then function collects all + the children recursively. + + \param rec if \c true collect all children recursively + \return list of children +*/ DataObjectList SUIT_DataObject::children( const bool rec ) { DataObjectList lst; @@ -217,50 +290,69 @@ DataObjectList SUIT_DataObject::children( const bool rec ) } /*! - Append new child object to the end of the children list + \brief Add new child object to the end of the children list. + \param obj child object being added */ - -void SUIT_DataObject::appendChild( SUIT_DataObject* theObj ) +void SUIT_DataObject::appendChild( SUIT_DataObject* obj ) { - insertChild( theObj, myChildren.count() ); + insertChild( obj, myChildren.count() ); } /*! - Insert new child object to the children list at specified position + \brief Insert new child object to the list of the children. + \param obj child object being added + \param position child position */ - -void SUIT_DataObject::insertChild( SUIT_DataObject* theObj, int thePosition ) +void SUIT_DataObject::insertChild( SUIT_DataObject* obj, int position ) { - if ( !theObj || myChildren.find( theObj ) != -1 ) + if ( !obj || myChildren.contains( obj ) ) return; - int pos = thePosition < 0 ? myChildren.count() : thePosition; - myChildren.insert( QMIN( pos, (int)myChildren.count() ), theObj ); - theObj->setParent( this ); + int pos = position < 0 ? myChildren.count() : position; + myChildren.insert( qMin( pos, (int)myChildren.count() ), obj ); + obj->setParent( this ); + signal()->emitInserted( obj, this ); } /*! - Removes the specified child object reference. + \brief Insert new child object into the list of the children (faster version of insertChild without signal). + \param obj child object being added + \param position child position */ +void SUIT_DataObject::insertChildAtPos( SUIT_DataObject* obj, int position ) +{ + if ( !obj )return; + int pos = position < 0 ? myChildren.count() : position; + myChildren.insert( qMin( pos, (int)myChildren.count() ), obj ); + obj->assignParent( this ); +} -void SUIT_DataObject::removeChild( SUIT_DataObject* theObj ) +/*! + \brief Remove the specified child object reference. + \param obj child object being removed + \param del if \c true, the child object is destroyed +*/ +void SUIT_DataObject::removeChild( SUIT_DataObject* obj, const bool del ) { - if ( !theObj ) + if ( !obj ) return; - bool ad = myChildren.autoDelete(); - myChildren.setAutoDelete( false ); - - if ( myChildren.remove( theObj ) ) - theObj->setParent( 0 ); + if ( myChildren.removeAll( obj ) ) { + signal()->emitRemoved( obj, this ); + obj->setParent( 0 ); - myChildren.setAutoDelete( ad ); + if ( del ) + obj->deleteLater(); + } } /*! - Replaces the specified child object by another object. + \brief Replace the specified child object by another object. + \param src child object being replaced + \param trg new child object + \param del if \c true, the previous object is destroyed + \return \c true if the object has been replaced */ - bool SUIT_DataObject::replaceChild( SUIT_DataObject* src, SUIT_DataObject* trg, const bool del ) { if ( !src || !trg ) @@ -287,9 +379,9 @@ bool SUIT_DataObject::replaceChild( SUIT_DataObject* src, SUIT_DataObject* trg, } /*! - Transfer the all children from specified object 'obj' to self. + \brief Change the parent for all children from specified object to this one. + \param obj object which children to be reparented */ - void SUIT_DataObject::reparentChildren( const SUIT_DataObject* obj ) { if ( !obj ) @@ -297,246 +389,659 @@ void SUIT_DataObject::reparentChildren( const SUIT_DataObject* obj ) DataObjectList lst; obj->children( lst ); - for ( DataObjectListIterator it( lst ); it.current(); ++it ) - it.current()->setParent( this ); + for ( DataObjectList::iterator it = lst.begin(); it != lst.end(); ++it ) + (*it)->setParent( this ); } /*! - Set the parent object. Remove itself from current parent children - and append itself to the new parent children list. + \brief Get the parent object. + \return parent object or 0 if this is top-level item */ +SUIT_DataObject* SUIT_DataObject::parent() const +{ + return myParent; +} -void SUIT_DataObject::setParent( SUIT_DataObject* theParent ) +/*! + \brief Change the parent object. + \param p new parent object +*/ +void SUIT_DataObject::setParent( SUIT_DataObject* p ) { - if ( theParent == parent() ) + if ( p == parent() ) return; if ( parent() ) parent()->removeChild( this ); - myParent = theParent; + myParent = p; if ( parent() ) parent()->appendChild( this ); } +void SUIT_DataObject::assignParent( SUIT_DataObject* p ) +{ + myParent = p; +} + /*! - Returns the parent object. + \brief Sets modification state of the object. + + When the object has been modified (modified is set to true) + a signal is emitted to notify the tree model and eventually redraw the data object. + + \param modified modified state */ +void SUIT_DataObject::setModified(bool modified) +{ + if ( _modified == modified ) + return; -SUIT_DataObject* SUIT_DataObject::parent() const + _modified = modified; + if ( _modified ) + signal()->emitModified( this ); +} + +/*! + \brief Get data object name. + + This method should be re-implemented in the subclasses. + Default implementation returns null string. + + \return object name +*/ +QString SUIT_DataObject::name() const { - return myParent; + return QString(); } +/*! + \brief Get object text data for the specified column. + + This method can be re-implemented in the subclasses. + Default implementation returns null string. + + Column with \a id = 0 (NameId) is supposed to be used + to get the object name (as it does the default implementation). + + \param id column id + \return object text data +*/ +QString SUIT_DataObject::text( const int id ) const +{ + return id == NameId ? name() : QString(); +} /*! - Connect to signal destroyed( SUIT_DataObject* ). + \brief Get data object icon for the specified column. + + This method can be re-implemented in the subclasses. + Default implementation returns null pixmap. + + The parameter \a id specifies the column identificator + + \param id column id + \return object icon for the specified column */ +QPixmap SUIT_DataObject::icon( const int /*id*/ ) const +{ + return QPixmap(); +} + +/*! + \brief Get data object color for the specified column. -bool SUIT_DataObject::connect( QObject* reciever, const char* slot ) + This method can be re-implemented in the subclasses. + Default implementation returns null color. + + The parameter \a id specifies the column identificator + + \param role color role + \param id column id + \return object color for the specified column +*/ +QColor SUIT_DataObject::color( const ColorRole /*role*/, const int /*id*/ ) const { - if ( !reciever || !slot ) - return false; + return QColor(); +} - if ( !mySignal ) - mySignal = new Signal( this ); +/*! + \brief Get data object tooltip for the specified column. - QObject::disconnect( mySignal, SIGNAL( destroyed( SUIT_DataObject* ) ), reciever, slot ); - return QObject::connect( mySignal, SIGNAL( destroyed( SUIT_DataObject* ) ), reciever, slot ); + This method can be re-implemented in the subclasses. + Default implementation returns null string. + + The parameter \a id specifies the column identificator + (to display, for example, in the tree view widget). + + \param id column id + \return object tooltip for the specified column +*/ +QString SUIT_DataObject::toolTip( const int /*id*/ ) const +{ + return QString(); } /*! - Disconnect from signal destroyed( SUIT_DataObject* ). + \brief Get data object status tip for the specified column. + + This method can be re-implemented in the subclasses. + Default implementation returns null string. + + The parameter \a id specifies the column identificator + + \param id column id + \return object status tip for the specified column */ +QString SUIT_DataObject::statusTip( const int /*id*/ ) const +{ + return QString(); +} -bool SUIT_DataObject::disconnect( QObject* reciever, const char* slot ) +/*! + \brief Get data object "what's this" information for the + specified column. + + This method can be re-implemented in the subclasses. + Default implementation returns null string. + + The parameter \a id specifies the column identificator + + \param id column id + \return object "what's this" information for the specified column +*/ +QString SUIT_DataObject::whatsThis( const int /*id*/ ) const { - if ( !reciever || !slot ) - return false; + return QString(); +} - if ( !mySignal ) - return true; +/*! + \brief Get data object font for the specified column. + + This method can be re-implemented in the subclasses. + Default implementation returns application default font. - return QObject::disconnect( mySignal, SIGNAL( destroyed( SUIT_DataObject* ) ), reciever, slot ); + The parameter \a id specifies the column identificator + + \param id column id + \return object font for the specified column +*/ +QFont SUIT_DataObject::font( const int /*id*/ ) const +{ + return QFont(); } /*! - Returns object name + \brief Get data object text alignment for the specified column. + + This method can be re-implemented in the subclasses. + Default implementation returns default alignment which + is Qt:AlignLeft. + + The parameter \a id specifies the column identificator + (to display, for example, in the tree view widget). + + \param id column id + \return object text alignment flags for the specified column */ +int SUIT_DataObject::alignment( const int /*id*/ ) const +{ + return Qt::AlignLeft; +} -void SUIT_DataObject::deleteLater() +bool SUIT_DataObject::expandable() const { - if ( !mySignal ) - mySignal = new Signal( this ); - - mySignal->emitSignal(); - mySignal->deleteLater(); + return true; } /*! - Returns object name + \brief Check if the object is visible. + + This method can be re-implemented in the subclasses. + Default implementation returns \c true (all objects are visible by default). + + \return \c true if this object is displayable or \c false otherwise */ +bool SUIT_DataObject::isVisible() const +{ + return true; +} -QString SUIT_DataObject::name() const +/*! + \brief Check if the object is draggable. + + This method can be re-implemented in the subclasses. + Default implementation returns \c false (all objects could not be dragged). + + \return \c true if it is possible to drag this object +*/ +bool SUIT_DataObject::isDraggable() const { - return QString::null; + return false; } /*! - Returns object icon + \brief Check if the drop operation for this object is possible. + + This method can be re-implemented in the subclasses. + Default implementation returns \c false (drop operation is not allowed). + + \return \c true if it is possible to drop one or more objects (currently selected) to this object */ +bool SUIT_DataObject::isDropAccepted() const +{ + return false; +} + +/*! + \brief Check if this object is enabled. -QPixmap SUIT_DataObject::icon() const + This method can be re-implemented in the subclasses. + Default implementation returns \c true (all objects are enabled). + + \return \c true if the user can interact with the item +*/ +bool SUIT_DataObject::isEnabled() const { - return QPixmap(); + return true; } /*! - Returns object text + \brief Check if this object is selectable. + + This method can be re-implemented in the subclasses. + Default implementation returns \c true (all objects are selectable). + + \return \c true if the item can be selected */ +bool SUIT_DataObject::isSelectable() const +{ + return true; +} -QString SUIT_DataObject::text( const int ) const +/*! + \brief Check if this object is checkable for the specified column. + + This method can be re-implemented in the subclasses. + Default implementation returns \c false (all objects are not checkable). + + \param id column id + \return \c true if the item can be checked or unchecked by the user + \sa isOn(), setOn() +*/ +bool SUIT_DataObject::isCheckable( const int /*id*/ ) const { - return QString::null; + return false; +} + +/*! + \brief Check if this object is can't be renamed in place + + This method can be re-implemented in the subclasses. + Default implementation returns \c false (all objects can not be renamed). + + \param id column id + \return \c true if the item can be renamed by the user in place (e.g. in the Object browser) +*/ +bool SUIT_DataObject::renameAllowed( const int /*id*/ ) const +{ + return false; } /*! - Returns object color + \brief Set name of the this object. + + This method can be re-implemented in the subclasses. + Default implementation returns \c false. + + \return \c true if rename operation finished successfully, \c false otherwise. */ +bool SUIT_DataObject::setName(const QString& /*name*/) { + return false; +} -QColor SUIT_DataObject::color( const ColorRole ) const +/*! + \brief Get the checked state of the object (if it is checkable) + for the specified column. + + Default implementation supports the checked state for the first + ("Name") column only. + + \param id column id + \return checked state of the object for the specified column + \sa setOn(), isCheckable() +*/ +bool SUIT_DataObject::isOn( const int id ) const { - return QColor(); + return id == NameId && myCheck; } /*! - Returns object tool tip + \brief Set the checked state of the object (if it is checkable) + for the specified column. + + Default implementation supports the checked state for the first + ("Name") column only. + + \param on new checked state of the object for the specified column + \param id column id + \sa isOn(), isCheckable() */ +void SUIT_DataObject::setOn( const bool on, const int id ) +{ + if( id == NameId ) + myCheck = on; +} -QString SUIT_DataObject::toolTip() const +/*! + \brief Get the "opened" state of the object. + \return "opened" state of the object + \sa setOpen() +*/ +bool SUIT_DataObject::isOpen() const { - return QString::null; + return myOpen; } /*! - Returns 'true' if it is possible to drag this object + \brief Set the "opened" state of the object. + \param on new "opened" state of the object + \sa isOpen() */ +void SUIT_DataObject::setOpen( const bool on ) +{ + myOpen = on; +} + +/*! + \brief Check if the specified column supports custom sorting. + + This method can be re-implemented in the subclasses. + Default implementation returns false ("Name" column does not require + custom sorting). -bool SUIT_DataObject::isDragable() const + \param id column id + \return \c true if column sorting should be customized + \sa compare() +*/ +bool SUIT_DataObject::customSorting( const int /*id*/ ) const { return false; } /*! - Returns 'true' if it is possible to drop an object "obj" to this object. -*/ + \brief Compares data from two items for sorting purposes. -bool SUIT_DataObject::isDropAccepted( SUIT_DataObject* ) + This method can be re-implemented in the subclasses. + Default implementation returns false ("Name" column does not require + custom sorting). + + This method is called only for those columns for which customSorting() + method returns \c true. + + \param left first data to compare + \param right second data to compare + \param id column id + \return result of the comparison + \sa customSorting() +*/ +bool SUIT_DataObject::compare( const QVariant& /*left*/, const QVariant& /*right*/, + const int /*id*/ ) const { return false; } /*! - Returns type of check possibility. + \brief Get the object unique indentification key. + + This method can be re-implemented in the subclasses. + Default implementation returns 0. + + \return object key */ +SUIT_DataObjectKey* SUIT_DataObject::key() const +{ + return 0; +} -SUIT_DataObject::CheckType SUIT_DataObject::checkType() const +/*! + \brief Get global signal handler. + \return the only instance of the signal handler +*/ +SUIT_DataObject::Signal* SUIT_DataObject::signal() { - return None; + if ( !mySignal ) + mySignal = new Signal(); + return mySignal; } /*! - Returns the checked state of the object. + \brief Connect to the signal handlerx + \param sig signal name + \param reciever signal receiver object + \param slot slot name + \return \c true if connection is successfull */ +bool SUIT_DataObject::connect( const char* sig, QObject* reciever, const char* slot ) +{ + if ( !reciever || !slot ) + return false; + + signal()->disconnect( signal(), sig, reciever, slot ); + return signal()->connect( signal(), sig, reciever, slot ); +} -bool SUIT_DataObject::isOn() const +/*! + \brief Disconnect from the signal handler + \param sig signal name + \param reciever signal receiver object + \param slot slot name + \return \c true if disconnection is successfull +*/ +bool SUIT_DataObject::disconnect( const char* sig, QObject* reciever, const char* slot ) { - return myCheck; + if ( !reciever || !slot ) + return false; + return signal()->disconnect( signal(), sig, reciever, slot ); } /*! - Sets the checked state of the object. + \brief Schedule this object for the late deleting. + + The object will be deleted when control returns to the event loop. + Note that entering and leaving a new event loop (e.g., by opening + a modal dialog) will not perform the deferred deletion; for the object + to be deleted, the control must return to the event loop from which + deleteLater() was called. */ +void SUIT_DataObject::deleteLater() +{ + if ( parent() ) + parent()->removeChild( this, false ); // to avoid infinite loop! + signal()->deleteLater( this ); +} -void SUIT_DataObject::setOn( const bool on ) +/*! + \brief Dump the object tree recursively to the standard output. + \param indent current indentation level +*/ +void SUIT_DataObject::dump( const int indent ) const { - myCheck = on; + QString strIndent = QString().fill( ' ', indent ); // indentation string + printf( "%s%s\n", strIndent.toLatin1().data(), name().toLatin1().data() ); + for ( DataObjectList::const_iterator it = myChildren.begin(); it != myChildren.end(); ++it ) + (*it)->dump( indent + 2 ); } /*! - \return the opened state of the object (used in Object Browser). + \class SUIT_DataObject::Signal + \brief Watcher class, responsible for the emitting signals on behalf of + the data objects. + + SUIT_DataObject class does not inherit from QObject for the performance + reasons, so it can not use signals/slots mechanism directly. + Instead it uses the only Signal object to emit the signals when the data + object is created, destroyed, inserted to the parent object or removed + from it. + + If some object needs to handle, for example, data object destroying, it can + use SUIT_DataObject::signal() method to connect the signal: + \code + MyHandler* h = new MyHandler(); + h->connect( SUIT_DataObject::signal(), SIGNAL(destroyed(SUIT_DataObject*)), + h, SLOT(onDestroyed(SUIT_DataObject*)) ); + \endcode + The same can be done by using static method SUIT_DataObject::connect(). + For example, + \code + MyHandler* h = new MyHandler(); + SUIT_DataObject::connect( SIGNAL(destroyed(SUIT_DataObject*)), + h, SLOT(onDestroyed(SUIT_DataObject*))); + \endcode */ -bool SUIT_DataObject::isOpen() const + +/*! + \brief Constructor. +*/ +SUIT_DataObject::Signal::Signal() +: QObject() { - return myOpen; } /*! - Sets the opened state of the object (used in Object Browser). + \brief Destructor. + + Destroys data object which are scheduled for the deleting with the deleteLater(). */ -void SUIT_DataObject::setOpen( const bool on ) +SUIT_DataObject::Signal::~Signal() { - myOpen = on; + for ( DataObjectList::Iterator it = myDelLaterObjects.begin(); + it != myDelLaterObjects.end(); ++it ) { + delete *it; + } + myDelLaterObjects.clear(); } /*! - Returns object personal indentification key. + \brief Emit signal about data object creation. + \param object data object being created */ +void SUIT_DataObject::Signal::emitCreated( SUIT_DataObject* object ) +{ + if ( object ) + emit created( object ); +} -SUIT_DataObjectKey* SUIT_DataObject::key() const +/*! + \brief Emit signal about data object destroying. + \param object data object being destroyed +*/ +void SUIT_DataObject::Signal::emitDestroyed( SUIT_DataObject* object ) { - return 0; + if ( object ) { + if ( myDelLaterObjects.contains( object ) ) + // object is being destroyed after calling deleteLater(): + // the signal has been already emitted from deleteLater() + // we should avoid repeating of the object destroying from + // the Signal destructor + myDelLaterObjects.removeAll( object ); + else + // object is being destroyed directly or via deleteLater() + emit destroyed( object ); + } } /*! - Dump this data object and its children to cout + \brief Emit signal about data object adding to the parent data object. + \param object data object being added + \param parent parent data object */ -void SUIT_DataObject::dump( const int indent ) const +void SUIT_DataObject::Signal::emitInserted( SUIT_DataObject* object, SUIT_DataObject* parent ) { - QString strIndent = QString().fill( ' ', indent ); // indentation string - printf( "%s%s\n", strIndent.latin1(), name().latin1() ); - for ( DataObjectListIterator it( myChildren ); it.current(); ++it ) // iterate all children - it.current()->dump( indent + 2 ); // dump every child with indent + 2 spaces + emit( inserted( object, parent ) ); } /*! - Class: SUIT_DataObject::Signal [Internal] + \brief Emit signal about data object removed from the parent data object. + \param object data object being removed + \param parent parent data object */ +void SUIT_DataObject::Signal::emitRemoved( SUIT_DataObject* object, SUIT_DataObject* parent ) +{ + emit( removed( object, parent ) ); +} -SUIT_DataObject::Signal::Signal( SUIT_DataObject* o ) -: QObject(), -myOwner( o ) +/*! + \brief Emit a signal to notify that the data object has been modified. + \param object data object that has been modified +*/ +void SUIT_DataObject::Signal::emitModified( SUIT_DataObject* object ) { + emit( modified( object ) ); } /*! - Destructor. + \brief Schedule data object for the late deleting. + \param object data object to be deleted later */ -SUIT_DataObject::Signal::~Signal() +void SUIT_DataObject::Signal::deleteLater( SUIT_DataObject* object ) { - SUIT_DataObject* o = myOwner; - myOwner = 0; - if ( o ) - { - o->mySignal = 0; - delete o; + if ( !myDelLaterObjects.contains( object ) ) { + emitDestroyed( object ); + myDelLaterObjects.append( object ); } } /*! - Set owner \a o. + \brief Updates necessary internal fields of data object */ -void SUIT_DataObject::Signal::setOwner( SUIT_DataObject* o ) +void SUIT_DataObject::update() { - myOwner = o; } /*! - emit signal destroed owner. -*/ -void SUIT_DataObject::Signal::emitSignal() + \brief return unique group identificator + + Groups of data objects are used for column information search. + Each column of data model has one or several registered group id + If object has the same group id as one of registered, the information + will be shown; the custom id of column will be passed into data() method + in order to identify column from point of view of data object + + */ +int SUIT_DataObject::groupId() const { - if ( myOwner ) - emit destroyed( myOwner ); + return 0; } +/*! + \brief return custom data for data object. + */ +QVariant SUIT_DataObject::customData(Qtx::CustomDataType /*type*/) { + return QVariant(); +} +/*! + \fn void SUIT_DataObject::Signal::created( SUIT_DataObject* object ); + \brief Emitted when data object is created. + \param object data object being created +*/ + +/*! + \fn void SUIT_DataObject::Signal::destroyed( SUIT_DataObject* object ); + \brief Emitted when data object is destroyed. + \param object data object being destroyed +*/ + +/*! + \fn void SUIT_DataObject::Signal::inserted( SUIT_DataObject* object, SUIT_DataObject* parent ); + \brief Emitted when data object is inserted to the parent data object. + \param object data object being created + \param parent parent data object +*/ + +/*! + \fn void SUIT_DataObject::Signal::removed( SUIT_DataObject* object, SUIT_DataObject* parent ); + \brief Emitted when data object is removed from the parent data object. + \param object data object being removed + \param parent parent data object +*/