|
Hormiga 1.0
|
00001 00002 /* 00003 # Hormiga - Software de cálculo programable. 00004 # 00005 # Copyright (C) 2008, 2009 Leonardo Román, Hugo J. Curti, Norma Ercoli, 00006 # Universidad Nacional del Centro de la Provincia de Buenos Aires 00007 # (UNCPBA) 00008 # 00009 # Este programa es parte de Hormiga. 00010 # 00011 # Hormiga es software libre. Puede redistribuirlo y/o modificarlo 00012 # bajo los términos de la Licencia Pública General de GNU según es 00013 # publicada por la Free Software Foundation, versión 2. Vea el archivo 00014 # COPIA (español, no oficial) o COPYING (inglés, oficial) en directorio 00015 # raíz. 00016 # 00017 # Hormiga se distribuye con la esperanza de que sea útil, pero SIN 00018 # NINGUNA GARANTÍA, incluso sin la garantía MERCANTIL implícita o sin 00019 # garantizar la CONVENIENCIA PARA UN PROPÓSITO PARTICULAR. Véase la 00020 # Licencia Pública General de GNU para más detalles. 00021 # 00022 # Debería haber recibido una copia de la Licencia Pública General junto 00023 # con Hormiga. Si no ha sido así, escriba a la Free Software 00024 # Foundation, Inc., en 675 Mass Ave, Cambridge, MA 02139, EEUU. 00025 # Añada también información sobre cómo contactar con usted mediante 00026 # correo electrónico y postal. 00027 # 00028 # This file is part of Hormiga. 00029 # 00030 # Hormiga is free software; you can redistribute it and/or modify 00031 # it under the terms of the GNU General Public License version 2 00032 # as published by the Free Software Foundation; see the file COPYING 00033 # in the top directory for details. 00034 # 00035 # Hormiga is distributed in the hope that it will be useful, 00036 # but WITHOUT ANY WARRANTY; without even the implied warranty of 00037 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00038 # GNU General Public License for more details. 00039 # 00040 # You should have received a copy of the GNU General Public License 00041 # along with Hormiga; if not, write to the Free Software 00042 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 00043 # USA 00044 */ 00045 00046 #include "step.h" 00047 #include "stdio.h" 00048 #include <QMetaType> 00049 Step::Step( T_STRING name ) 00050 { 00051 this->name = name ; 00052 this->execBlock = NULL ; 00053 this->stepsNeeded = NULL ; 00054 this->captures = NULL ; 00055 this->reports = NULL ; 00056 this->condition = NULL ; 00057 unsatisfiedDependencesCount = 0 ; 00058 this->currentState = Step::Satisfied ; 00059 this->alreadyExecuted = false ; 00060 00061 if ( QMetaType::type("Step") == 0 ) 00062 { /* We need to register our types used in signals */ 00063 qRegisterMetaType<Step*>("Step") ; 00064 qRegisterMetaType<Step::state>("Step::state") ; 00065 } 00066 } 00067 00068 Step::~Step() 00069 { 00070 if ( this->stepsNeeded != NULL ) delete this->stepsNeeded ; 00071 if ( this->captures != NULL ) delete this->captures ; 00072 if ( this->reports != NULL ) delete this->reports ; 00073 if ( this->execBlock != NULL ) delete this->execBlock ; 00074 if ( this->condition != NULL ) delete this->condition ; 00075 } 00076 00077 00078 T_STRING Step::toString () const 00079 { 00080 return ( this->name ) ; 00081 } 00082 00083 T_STRING Step::getName () 00084 { 00085 return ( this->name ) ; 00086 } 00087 00088 void Step::run () 00089 { 00090 this->exec( true ) ; 00091 } 00092 00093 bool Step::exec ( bool interactive ) 00094 { 00095 if ( this->currentState == Step::NotSatisfied ) 00096 return ( false ) ; 00097 this->changeState( Step::Executing ) ; 00098 this->alreadyExecuted = true ; 00099 if ( this->captures != NULL && interactive ) 00100 { 00101 /* We will wait here for user input (if any GUI is connected for) */ 00102 emit needInput ( this , this->captures ) ; 00103 /* If the GUI is not "bloking" on connected slot then will need to sleep 00104 the Step thread 00105 */ 00106 } 00107 00108 execSleep.lock() ; 00109 bool result = this->execBlock->exec() ; 00110 execSleep.unlock() ; 00111 00112 if ( this->reports != NULL && interactive ) 00113 emit reportOutput( this, this->reports ) ; 00114 00115 /* Are conditions OK ? */ 00116 if ( this->condition != NULL && ! this->condition->eval() ) 00117 { 00118 result = FALSE ; 00119 this->showMessage( 2, this->condition->getText() ) ; 00120 } 00121 /* Wait for GUI to show the reports, if is any */ 00122 execSleep.lock() ; 00123 // Se cumplen las condiciones ? 00124 if ( result ) 00125 { 00126 this->changeState( Step::Accepted ) ; 00127 } else { 00128 this->changeState( Step::Satisfied ) ; 00129 } 00130 execSleep.unlock() ; 00131 return ( true ) ; 00132 } 00133 00134 void Step::setStepNeeds ( T_STEP_LIST *stepsNeeded ) 00135 { 00136 if ( stepsNeeded == NULL ) 00137 return ; 00138 this->stepsNeeded = stepsNeeded ; 00139 for ( int i = 0 ; i < stepsNeeded->count() ; i++ ) 00140 { 00141 QObject::connect ( stepsNeeded->at( i ) , SIGNAL ( 00142 stateChanged(Step*,Step::state,Step::state) ) , 00143 this , SLOT ( 00144 notifyStepState( Step*, Step::state,Step::state) ) 00145 ) ; 00146 } 00147 00148 this->unsatisfiedDependencesCount = stepsNeeded->count() ; 00149 // By now... this is the unique option: 00150 this->changeState( Step::NotSatisfied ) ; 00151 } 00152 00153 void Step::setExecutionBlock ( Statement *execBlock ) 00154 { 00155 this->execBlock = execBlock ; 00156 } 00157 00158 void Step::setCaptures ( T_CAPTURE_LIST *clist ) 00159 { 00160 this->captures = clist ; 00161 } 00162 00163 void Step::setReports ( T_REPORT_LIST *reports ) 00164 { 00165 this->reports = reports ; 00166 } 00167 00168 void Step::setStepCondition ( StepCondition *condition ) 00169 { 00170 this->condition = condition ; 00171 } 00172 00173 void Step::changeState ( Step::state newState ) 00174 { 00175 if ( this->currentState != newState ) 00176 { 00177 Step::state oldState = this->currentState ; 00178 this->currentState = newState ; 00179 emit stateChanged( this , newState , oldState ) ; 00180 } 00181 } 00182 00183 /* Slots */ 00184 void Step::notifyStepState( Step* peer , Step::state newState , 00185 Step::state oldState ) 00186 { 00187 /* - de <cualquier_estado> a [aceptado] : counter-- 00188 * - de [aceptado] a <cualquier_estado> : counter ++ 00189 * Deberiamos verificar que 'peer' sea uno de los de la lista de 00190 * dependencias ? Por ahora "confiaremos" en que si. 00191 */ 00192 if ( ( newState == Step::Accepted ) || ( oldState == Step::Accepted ) ) 00193 printf("Step %s notified. Step %s state changed from %d to %d\n", 00194 this->getName().toAscii().data(), 00195 peer->getName().toAscii().data(), oldState, newState ); 00196 if ( newState == Step::Accepted ) 00197 { 00198 this->unsatisfiedDependencesCount-- ; 00199 if ( this->unsatisfiedDependencesCount == 0 ) 00200 { 00201 this->changeState( Step::Satisfied ) ; 00202 // We should re-run this step ? -> this->start() ; 00203 if ( this->alreadyExecuted ) 00204 this->exec( false ) ; // Re-run me serialized ;) 00205 } 00206 } 00207 else if ( oldState == Step::Accepted ) 00208 { 00209 this->unsatisfiedDependencesCount++ ; 00210 this->changeState( Step::NotSatisfied ) ; 00211 } 00212 } 00213 00214 00215 StepConditionSingle::StepConditionSingle ( Operand *condition , T_STRING text ) 00216 { 00217 this->condition = condition ; 00218 this->text = text ; 00219 } 00220 00221 StepConditionSingle::~StepConditionSingle() 00222 { 00223 if ( this->condition != NULL ) delete this->condition ; 00224 } 00225 00226 bool StepConditionSingle::eval() 00227 { 00228 if ( this->condition == NULL ) return TRUE ; 00229 return ( ( this->condition->getValue() != FALSE )? TRUE : FALSE ) ; 00230 } 00231 00232 T_STRING StepConditionSingle::getText() 00233 { 00234 return this->text ; 00235 } 00236 00237 00238 00239 StepConditionComposite::StepConditionComposite ( T_STEP_CONDITIONS_LIST* list ) 00240 { 00241 this->list = list ; 00242 this->last = NULL ; 00243 } 00244 00245 StepConditionComposite::~StepConditionComposite () 00246 { 00247 for ( int i = 0 ; i < list->count() ; i++ ) 00248 delete list->takeFirst() ; 00249 delete this->list ; 00250 } 00251 00252 bool StepConditionComposite::eval() 00253 { 00254 for ( int i = 0 ; i < list->count() ; i++ ) 00255 { 00256 this->last = this->list->at( i ) ; 00257 if ( ! this->last->eval() ) 00258 return FALSE ; 00259 } 00260 return TRUE ; 00261 } 00262 00263 T_STRING StepConditionComposite::getText() 00264 { 00265 if ( this->last != NULL ) 00266 return this->last->getText() ; 00267 return "" ; 00268 }