+// Copyright (C) 2007-2023 CEA/DEN, EDF R&D, 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, 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
+// 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_Study.h"
#include "SUIT_Desktop.h"
SUIT_Study::SUIT_Study( SUIT_Application* app )
: QObject(),
myApp( app ),
+myName( "" ),
myIsSaved( false ),
myIsModified( false ),
-myName( "" )
+myBlockChangeState( false )
{
static int _id = 0;
myId = ++_id;
myRoot = new SUIT_DataObject();
- myOperations.setAutoDelete( false );
}
/*!Destructor.*/
*/
SUIT_Operation* SUIT_Study::activeOperation() const
{
- return myOperations.current();
+ return myOperations.count() > 0 ? myOperations.last() : 0;
}
/*!
- *\retval TRUE - if study saved, else FALSE.
+ *\retval \c true - if study saved, else \c false.
*/
bool SUIT_Study::isSaved() const
{
}
/*!
- *\retval TRUE - if study modified, else FALSE.
+ *\retval \c true - if study modified, else \c false.
*/
bool SUIT_Study::isModified() const
{
/*!
*Close document. NOT IMPLEMENTED.
*/
-void SUIT_Study::closeDocument(bool permanently)
+void SUIT_Study::closeDocument(bool /*permanently*/)
{
}
-void SUIT_Study::createDocument()
+/*!
+ Custom document initialization to be performed \n
+ within onNewDoc() handler can be put here
+*/
+bool SUIT_Study::createDocument( const QString& )
{
- /*! Custom document initialization to be performed \n
- * within onNewDoc() handler can be put here
- */
+ return true;
}
/*!
- * Open document. Sets file name. return true.
+ * Open document. Sets file name. return \c true.
*/
bool SUIT_Study::openDocument( const QString& fileName )
{
}
/*!
- *\retval TRUE - if document saved successful, else FALSE.
+ *\retval \c true - if document saved successful, else \c false.
*/
bool SUIT_Study::saveDocument()
{
*/
void SUIT_Study::abortAllOperations()
{
- SUIT_Operation* aOperation = 0;
- while ( aOperation = myOperations.current() )
- {
- aOperation->abort();
- myOperations.pop();
+ myBlockChangeState = true;
+ while ( !myOperations.isEmpty() ) {
+ Operations::iterator it = myOperations.begin();
+ (*it)->abort();
}
+ myBlockChangeState = false;
+ myOperations.clear();
}
/*!
myIsModified = on;
}
+/*!
+ Set study modified to \a on.
+ */
+void SUIT_Study::Modified()
+{
+ setIsModified( true );
+ sendChangesNotification();
+}
+
/*!
Set root object.
*/
if ( myRoot == obj )
return;
+ // This is necessary in order not to destroy the complete tree of objects
+ if ( obj )
+ obj->reparentChildren( myRoot );
+
delete myRoot;
myRoot = obj;
}
}
/*!
- Stop operation.
- */
-void SUIT_Study::stopOperation()
+ * \brief Verifies whether operation can be activated above already started ones
+ * \param theOp - operation to be checked
+ * \return NULL if operation can be activated, pointer to operation which denies
+ * starting tested operation
+*
+* Verifies whether operation can be activated above already started ones. This method
+* is called from SUIT_Study::start() and SUIT_Study::resume() methods.
+*/
+SUIT_Operation* SUIT_Study::blockingOperation( SUIT_Operation* theOp ) const
{
- myOperations.pop();
- if ( myOperations.current() )
- myOperations.current()->resume();
- myIsModified = true;
+ if( theOp->isGranted() )
+ return 0;
+
+ Operations tmpOps( myOperations );
+ for ( Operations::const_iterator it = tmpOps.end(); it != tmpOps.begin(); )
+ {
+ it--;
+ SUIT_Operation* anOp = *it;
+ if ( anOp != 0 && anOp!= theOp && !anOp->isValid( theOp ) )
+ return anOp;
+ }
+
+ return 0;
}
/*!
- * Set can start operation \a theOperation.
- *\retval FALSE - if can't start.
- */
-bool SUIT_Study::canStartOperation( SUIT_Operation* theOperation )
+ * \brief Starts operation
+ * \param theOp - operation to be started
+ * \param toCheck - if parameters is equal \c true then checking performed whether
+ * all already started operations allow to start this operation above them (default
+ * value is \c true
+ * \return \c true if operation is started, \c false otherwise
+*
+* Verifies whether theOp operation can be started above already started ones (if toCheck
+* parameter is equal \c true) and starts it
+*/
+bool SUIT_Study::start( SUIT_Operation* theOp, const bool toCheck )
+{
+ if ( !theOp || myOperations.contains( theOp ) )
+ return false;
+
+ theOp->setExecStatus( SUIT_Operation::Rejected );
+ theOp->setStudy( this );
+
+ if ( !theOp->isReadyToStart() )
+ return false;
+
+ if ( toCheck )
+ {
+ while ( SUIT_Operation* anOp = blockingOperation( theOp ) )
+ {
+ int anAnsw = SUIT_MessageBox::question( application()->desktop(),
+ tr( "OPERATION_LAUNCH" ), tr( "PREVIOUS_NOT_FINISHED" ),
+ tr( "CONTINUE" ), tr( "CANCEL" ) );
+
+ if ( anAnsw == 1 )
+ return false;
+ else
+ anOp->abort();
+ }
+ }
+
+ SUIT_Operation* anOp = activeOperation();
+ if ( anOp )
+ {
+ activeOperation()->suspendOperation();
+ anOp->setState( SUIT_Operation::Suspended );
+ }
+
+ theOp->setState( SUIT_Operation::Running );
+ myOperations.append( theOp );
+
+ emit theOp->started( theOp );
+ operationStarted( theOp );
+ theOp->startOperation();
+
+ return true;
+}
+
+/*!
+ * \brief Aborts operation
+ * \param theOp - operation to be aborted
+ * \return \c true if operation is aborted successfully
+*
+* Verifies whether operation already started and aborts it in this case (sets execution
+* status to Rejected and stops operation)
+*/
+bool SUIT_Study::abort( SUIT_Operation* theOp )
+{
+ if ( !theOp || !myOperations.contains( theOp ) )
+ return false;
+
+ theOp->setExecStatus( SUIT_Operation::Rejected );
+
+ theOp->abortOperation();
+ operationAborted( theOp );
+ emit theOp->aborted( theOp );
+
+ stop( theOp );
+
+ return true;
+}
+
+/*!
+ * \brief Commits operation
+ * \param theOp - operation to be committed
+ * \return \c true if operation is committed successfully
+*
+* Verifies whether operation already started and commits it in this case (sets execution
+* status to Accepted and stops operation)
+*/
+bool SUIT_Study::commit( SUIT_Operation* theOp )
+{
+ if ( !theOp || !myOperations.contains( theOp ) )
+ return false;
+
+ theOp->setExecStatus( SUIT_Operation::Accepted );
+
+ theOp->commitOperation();
+ operationCommited( theOp );
+ emit theOp->committed( theOp );
+
+ stop( theOp );
+
+ emit studyModified( this );
+
+ return true;
+}
+
+/*!
+ * \brief Commits operation
+ * \param theOp - operation to be committed
+ * \return \c true if operation is suspended successfully
+*
+* Verifies whether operation already started and suspends it in this case. Operations
+* ususlly are suspended to start other one above them.
+*/
+bool SUIT_Study::suspend( SUIT_Operation* theOp )
+{
+ if ( !theOp || !myOperations.contains( theOp ) || theOp->state() == SUIT_Operation::Suspended )
+ return false;
+
+ theOp->setState( SUIT_Operation::Suspended );
+ theOp->suspendOperation();
+ emit theOp->suspended( theOp );
+ return true;
+}
+
+
+/*!
+ * \brief Resumes operation
+ * \param theOp - operation to be resumed
+ * \return \c true if operation is aborted successfully
+*
+* Verifies whether operation already started but suspended and resumesit in this case.
+*/
+bool SUIT_Study::resume( SUIT_Operation* theOp )
{
- SUIT_Operation* anActiveOperation = (SUIT_Operation*)activeOperation();
- if ( anActiveOperation )
+ if ( !theOp || !myOperations.contains( theOp ) ||
+ theOp->state() == SUIT_Operation::Running ||
+ blockingOperation( theOp ) != 0 )
+ return false;
+
+ if ( myOperations.count() > 0 )
+ suspend( myOperations.last() );
+
+ theOp->setState( SUIT_Operation::Running );
+ theOp->resumeOperation();
+
+ // Move operation at the end of list in order to sort it in the order of activation.
+ // As result active operation is a last operation of list, operation which was active
+ // before currently active operation is located before it and so on
+ myOperations.removeAll( theOp );
+ myOperations.append( theOp );
+
+ emit theOp->resumed( theOp );
+ return true;
+}
+
+/*!
+ * \brief Stops operation
+ * \param theOp - operation to be stopped
+*
+* Stops operation. This private method is called from abort() and commit() ones to perform
+* common actions when operation is stopped
+*/
+void SUIT_Study::stop( SUIT_Operation* theOp )
+{
+ theOp->setState( SUIT_Operation::Waiting );
+ myOperations.removeAll( theOp );
+
+ // get last operation which can be resumed
+ SUIT_Operation* aResultOp = 0;
+
+ QListIterator<SUIT_Operation*> it (myOperations);
+ it.toBack();
+ while( it.hasPrevious() )
{
- if ( !theOperation->isGranted() )
+ SUIT_Operation* anOp = it.previous();
+ if ( anOp && anOp != theOp && blockingOperation( anOp ) == 0 )
{
- if ( !anActiveOperation->isValid( theOperation ) )
- {
- // Ask user about existing operation
- int anAnsw = SUIT_MessageBox::warn2( application()->desktop(), tr( "Operation launch" ),
- tr( "Previous operation is not finished and will be aborted." ),
- tr( "Continue" ), tr( "Cancel" ), 0, 1, 1 );
- if ( anAnsw == 1 )
- return false;
-
- anActiveOperation->abort();
- myOperations.pop();
- myOperations.push( theOperation );
- return true;
- }
+ aResultOp = anOp;
+ break;
}
- anActiveOperation->suspend();
}
- myOperations.push( theOperation );
+ theOp->stopOperation();
+ operationStopped( theOp );
+ emit theOp->stopped( theOp );
+
+ if ( aResultOp )
+ resume( aResultOp );
+}
+
+/*!
+ * \brief Get all started operations
+ * \return List of all started operations
+*/
+const QList<SUIT_Operation*>& SUIT_Study::operations() const
+{
+ return myOperations;
+}
+
+/*!
+ * \brief Perform some actions when operation starting
+*/
+void SUIT_Study::operationStarted( SUIT_Operation* op )
+{
+ if ( !op )
+ return;
+
+ if ( op->testFlags( SUIT_Operation::Transaction ) )
+ op->openTransaction();
+}
+
+/*!
+ * \brief Perform some actions when operation aborted
+*/
+void SUIT_Study::operationAborted( SUIT_Operation* op )
+{
+ if ( op->testFlags( SUIT_Operation::Transaction ) )
+ op->abortTransaction();
+}
+
+/*!
+ * \brief Perform some actions when operation commited
+*/
+void SUIT_Study::operationCommited( SUIT_Operation* op )
+{
+ if ( op->testFlags( SUIT_Operation::Transaction ) )
+ op->commitTransaction( op->operationName() );
+}
+
+/*!
+ * \brief Perform some actions when operation stopped
+*/
+void SUIT_Study::operationStopped( SUIT_Operation* )
+{
+}
+
+/*!
+ * \brief Opens transaction for data modifications.
+*/
+bool SUIT_Study::openTransaction()
+{
+ return true;
+}
+
+/*!
+ * \brief Aborts transaction and all performed data modifications.
+*/
+bool SUIT_Study::abortTransaction()
+{
return true;
}
+
+/*!
+ * \brief Commits transaction and all performed data modifications.
+*/
+bool SUIT_Study::commitTransaction( const QString& )
+{
+ return true;
+}
+
+/*!
+ * \brief Returns \c true if transaction is opened.
+*/
+bool SUIT_Study::hasTransaction() const
+{
+ return false;
+}
+
+/*!
+ * \brief Restores the study state.
+ */
+void SUIT_Study::restoreState(int /*savePoint*/)
+{
+}