#include "SUIT_DataObject.h"
#include "SUIT_MessageBox.h"
#include "SUIT_Application.h"
+#include <qvaluevector.h>
/*!\class SUIT_Study
* Support study management. Object management. Operation management.
myApp( app ),
myIsSaved( false ),
myIsModified( false ),
-myName( "" )
+myName( "" ),
+myBlockChangeState( false )
{
static int _id = 0;
myRoot = new SUIT_DataObject();
myOperations.setAutoDelete( false );
+
+ connect( this, SIGNAL( changeOperationState( bool ) ), this, SLOT( onChangeOperationState( bool ) ) );
+
+ myOperations.setAutoDelete( false );
}
/*!Destructor.*/
*/
SUIT_Operation* SUIT_Study::activeOperation() const
{
- return myOperations.current();
+ return myOperations.count() > 0 ? myOperations.getLast() : 0;
}
/*!
*/
void SUIT_Study::abortAllOperations()
{
- SUIT_Operation* aOperation = 0;
- while ( aOperation = myOperations.current() )
- {
- aOperation->abort();
- myOperations.pop();
- }
+ myBlockChangeState = true;
+ for( SUIT_Operation* op = myOperations.first(); op; op = myOperations.next() )
+ op->abort();
+ myBlockChangeState = false;
+ myOperations.clear();
}
/*!
}
/*!
- 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 );
+ SUIT_Operation* anOp = 0;
+ for ( anOp = tmpOps.last(); anOp; anOp = tmpOps.prev() )
+ {
+ 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 TRUE then checking performed whether
+ * all already started operations allow to start this operation above them (default
+ * value is TRUE
+ * \return TRUE if operation is started, FALSE otherwise
+*
+* Verifies whether theOp operation can be started above already started ones (if toCheck
+* parameter is equal TRUE) and starts it
+*/
+bool SUIT_Study::start( SUIT_Operation* theOp, const bool toCheck )
{
- SUIT_Operation* anActiveOperation = (SUIT_Operation*)activeOperation();
- if ( anActiveOperation )
+ if ( !theOp || myOperations.find( theOp ) >= 0 )
+ return false;
+
+ theOp->setExecStatus( SUIT_Operation::Rejected );
+ theOp->setStudy( this );
+
+ if ( !theOp->isReadyToStart() )
+ return false;
+
+ if ( toCheck )
{
- if ( !theOperation->isGranted() )
+ while( SUIT_Operation* anOp = blockingOperation( theOp ) )
{
- 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;
- }
+ int anAnsw = SUIT_MessageBox::warn2( application()->desktop(),
+ tr( "OPERATION_LAUNCH" ), tr( "PREVIOUS_NOT_FINISHED" ),
+ tr( "CONTINUE" ), tr( "CANCEL" ), 0, 1, 1 );
+
+ if( anAnsw == 1 )
+ return false;
+ else
+ anOp->abort();
}
- anActiveOperation->suspend();
}
- myOperations.push( theOperation );
+ 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 );
+ theOp->startOperation();
+
+ return true;
+}
+
+/*!
+ * \brief Aborts operation
+ * \param theOp - operation to be aborted
+ * \return 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.find( theOp ) == -1 )
+ return false;
+
+ theOp->abortOperation();
+ theOp->setExecStatus( SUIT_Operation::Rejected );
+ emit theOp->aborted( theOp );
+ stop( theOp );
+ return true;
+}
+
+/*!
+ * \brief Commits operation
+ * \param theOp - operation to be committed
+ * \return 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.find( theOp ) == -1 )
+ return false;
+
+ theOp->commitOperation();
+ theOp->setExecStatus( SUIT_Operation::Accepted );
+ emit theOp->committed( theOp );
+ stop( theOp );
+ emit studyModified( this );
+ return true;
+}
+
+/*!
+ * \brief Commits operation
+ * \param theOp - operation to be committed
+ * \return 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.find( theOp ) == -1 || 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 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 )
+{
+ if ( !theOp || myOperations.find( theOp ) == -1 ||
+ 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.remove( 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.remove( theOp );
+
+ // get last operation which can be resumed
+ SUIT_Operation* anOp, *aResultOp = 0;
+ for( anOp = myOperations.last(); anOp; anOp = myOperations.prev() )
+ if ( anOp && anOp != theOp && blockingOperation( anOp ) == 0 )
+ {
+ aResultOp = anOp;
+ break;
+ }
+
+ emit theOp->stopped( theOp );
+ if ( aResultOp )
+ resume( aResultOp );
+}
+
+/*!
+ * \brief Get all started operations
+ * \return List of all started operations
+*/
+const QPtrList<SUIT_Operation>& SUIT_Study::operations() const
+{
+ return myOperations;
+}
+
+
+
+
+
+
+
+
+
+
#include "SUIT_Operation.h"
#include <qobject.h>
-#include <qptrstack.h>
+#include <qptrlist.h>
class SUIT_DataObject;
class SUIT_Application;
+class QDialog;
#ifdef WIN32
#pragma warning( disable:4251 )
class SUIT_EXPORT SUIT_Study : public QObject
{
Q_OBJECT
+
public:
SUIT_Study( SUIT_Application* );
virtual ~SUIT_Study();
SUIT_DataObject* root() const;
QString studyName() const;
SUIT_Application* application() const;
- SUIT_Operation* activeOperation() const;
virtual bool isSaved() const;
virtual bool isModified() const;
bool saveDocument();
virtual bool saveDocumentAs( const QString& );
- virtual void abortAllOperations();
-
virtual void update();
virtual void sendChangesNotification();
+ // Operation management
+ SUIT_Operation* activeOperation() const;
+ virtual void abortAllOperations();
+ const QPtrList<SUIT_Operation>& operations() const;
+
+ virtual SUIT_Operation* blockingOperation( SUIT_Operation* ) const;
+
+ bool start( SUIT_Operation*, const bool check = true );
+ bool abort( SUIT_Operation* );
+ bool commit( SUIT_Operation* );
+ bool suspend( SUIT_Operation* );
+ bool resume( SUIT_Operation* );
+
signals:
void studyModified( SUIT_Study* );
virtual void setRoot( SUIT_DataObject* );
virtual void setStudyName( const QString& );
- void stopOperation();
- bool canStartOperation( SUIT_Operation* );
-
-protected:
- typedef QPtrStack<SUIT_Operation> OperationsStack;
-
-protected:
- OperationsStack myOperations;
+private:
+ typedef QPtrList<SUIT_Operation> Operations;
+ void stop( SUIT_Operation* );
private:
int myId;
QString myName;
bool myIsSaved;
bool myIsModified;
-
- friend class SUIT_Operation;
+ Operations myOperations;
+ bool myBlockChangeState;
};
#ifdef WIN32