|
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 "mainwindow.h" 00047 #include "ui_mainwindow.h" 00048 #include "stdio.h" 00049 00050 #include <QMessageBox> 00051 #include <QScrollArea> 00052 #include <QComboBox> 00053 00054 #include <qwt_slider.h> 00055 #include <qwt_thermo.h> 00056 #include <qwt_data.h> 00057 /* QwtDataHPlot2D 00058 * Helper Class for Ploter 00059 */ 00060 QwtData * QwtDataHPlot2D::copy () const { 00061 QwtDataHPlot2D* toRet = new QwtDataHPlot2D( this->fi , QObject::parent(), true ); 00062 toRet->vx = this->vx ; 00063 toRet->vy = this->vy ; 00064 toRet->vsize = this->vsize ; 00065 return toRet ; 00066 } 00067 size_t QwtDataHPlot2D::size () const { 00068 return this->vsize ; 00069 } 00070 double QwtDataHPlot2D::x (size_t i) const { 00071 return vx[i] ; 00072 } 00073 double QwtDataHPlot2D::y (size_t i) const { 00074 return vy[i] ; 00075 } 00076 QwtDataHPlot2D::QwtDataHPlot2D ( FunctionInstanceIterator* fi, QObject *parent , bool isCopy ) 00077 : QObject(parent) { 00078 this->isCloned = isCopy ; 00079 this->fi = fi ; 00080 if ( ! isCopy ) { 00081 size_t s = fi->iterationsCount() ; 00082 vx = new double[s] ; 00083 vy = new double[s] ; 00084 int i = 0 ; 00085 const double* d = fi->first() ; 00086 do { 00087 vx[i] = d[0] ; 00088 vy[i] = d[1] ; 00089 i++ ; 00090 } while ( fi->next() != NULL ) ; 00091 this->vsize = i ; 00092 } 00093 } 00094 QwtDataHPlot2D::~QwtDataHPlot2D () { 00095 if ( ! this->isCloned ) { 00096 delete[] this->vx ; 00097 delete[] this->vy ; 00098 } 00099 } 00100 00101 00102 MainWindow::MainWindow( CoreInterface *core , QWidget *parent ) 00103 : QMainWindow(parent), ui(new Ui::MainWindowClass) 00104 { 00105 ui->setupUi(this); 00106 this->currentCapts = NULL ; 00107 this->currentStep = NULL ; 00108 this->core = core ; 00109 QObject::connect( core, SIGNAL( stepCreated( Step* ) ), 00110 this, SLOT( addStep( Step* ) ) ) ; 00111 QObject::connect( ui->stepList, 00112 SIGNAL( itemDoubleClicked ( QListWidgetItem* ) ), 00113 this, SLOT( executeStep ( QListWidgetItem* ) ) ) ; 00114 // For Error reports... 00115 QObject::connect( core, SIGNAL( coreMessage(QString,int)) , 00116 this, SLOT( showMessage(QString,int) ) ) ; 00117 } 00118 00119 00120 void MainWindow::clear () 00121 { 00122 this->currentCapts = NULL ; 00123 this->currentStep = NULL ; 00124 this->ui->stepList->clear() ; 00125 inputs.clear() ; 00126 if ( ui->splitter->widget( 1 ) ) delete ui->splitter->widget( 1 ) ; 00127 } 00128 00129 MainWindow::~MainWindow() 00130 { 00131 delete ui; 00132 } 00133 00134 00135 void MainWindow::addStep ( Step *newStep ) 00136 { 00137 /* Este slot se conecta al CORE */ 00138 ui->stepList->addItem( newStep->getName() ); 00139 QObject::connect( newStep, SIGNAL(stateChanged(Step*,Step::state,Step::state)), 00140 this, SLOT(changeState(Step*,Step::state,Step::state)) ); 00141 /* The next connection is forced to be Synchronic */ 00142 QObject::connect( newStep, 00143 SIGNAL(needInput( Step*, T_CAPTURE_LIST* )), 00144 this, SLOT(showCapturesGUI ( Step*, T_CAPTURE_LIST* )), 00145 Qt::BlockingQueuedConnection ) ; 00146 QObject::connect( newStep, 00147 SIGNAL( reportOutput(Step*, T_REPORT_LIST*) ), 00148 this, SLOT( showReportsGUI(Step*, T_REPORT_LIST*) ), 00149 Qt::BlockingQueuedConnection ) ; 00150 } 00151 00152 void MainWindow::changeState( Step* peer , Step::state newState , Step::state oldState ) 00153 { 00154 /* Este slot se conecta a los Steps */ 00155 QListWidgetItem *s = NULL ; 00156 for ( int i = 0 ; i < ui->stepList->count() ; i ++ ) { 00157 s = ui->stepList->item(i) ; 00158 if ( s->text() == peer->getName() ) { 00159 QBrush b = s->foreground() ; 00160 switch ( newState ) { 00161 case Step::NotSatisfied: b.setColor( Qt::lightGray ) ; break ; 00162 case Step::Satisfied: b.setColor( Qt::darkBlue ) ; break ; 00163 case Step::Executing: b.setColor( Qt::darkRed ) ; break ; 00164 case Step::Accepted: b.setColor( Qt::darkGreen ) ; break ; 00165 } 00166 s->setForeground( b ) ; 00167 return ; 00168 } 00169 } 00170 } 00171 00172 00173 void MainWindow::showCapturesGUI ( Step* emisor , T_CAPTURE_LIST* captures ) 00174 { 00175 /* Este slot se conecta a los Steps */ 00176 emisor->sleep(); 00177 inputs.clear() ; 00178 if ( ui->splitter->widget( 1 ) ) delete ui->splitter->widget( 1 ) ; 00179 QFrame *frame = new QFrame() ; 00180 QVBoxLayout *vLayout = new QVBoxLayout(frame) ; 00181 for ( int i = 0 ; i < captures->count() ; i++ ) 00182 { 00183 Capture *c = captures->at( i ) ; 00184 QLayout *layout = NULL ; 00185 switch ( c->getCaptureType() ) 00186 { 00187 case Capture::CTXT : layout = getCaptureInputTXT( c, frame ) ; break ; 00188 case Capture::CGUI : layout = getCaptureInputGUI( c, frame ) ; break ; 00189 case Capture::CIMG : layout = getCRLayoutIMG( (CR_Image*) c , frame ) ; break ; 00190 case Capture::CSEL : layout = getCRLayoutSEL( (CR_Select*) c, frame, false ) ; break ; 00191 case Capture::CPLOT : layout = getCRLayoutPLOT( (CR_FunctionIterator*) c , frame ) ; break ; 00192 } 00193 vLayout->addLayout( layout ) ; 00194 } 00195 QPushButton *okButton = new QPushButton( tr("Ok") , frame ) ; 00196 vLayout->addWidget( okButton ) ; 00197 QObject::connect( okButton, 00198 SIGNAL( clicked()) , 00199 this, SLOT( acceptCaptures()) ) ; 00200 QPushButton *printButton = new QPushButton( tr("Print...") , frame ) ; 00201 vLayout->addWidget( printButton ) ; 00202 QObject::connect( printButton, 00203 SIGNAL( clicked()) , 00204 this, SLOT( print() ) ) ; 00205 QScrollArea *scrollArea = new QScrollArea ; 00206 scrollArea->setWidget( frame ) ; 00207 ui->splitter->addWidget( scrollArea ) ; 00208 this->currentCapts = captures ; 00209 this->currentStep = emisor ; 00210 } 00211 00212 QLayout *MainWindow::getCaptureInputGUI( Capture* capture, QFrame *frame ) 00213 { 00214 CaptureGUI *c = (CaptureGUI*) capture ; 00215 QLabel *label = new QLabel( tr( c->getLabel().toAscii().data() ), frame ) ; 00216 00217 QwtSlider *slider = new QwtSlider ( frame, Qt::Horizontal, QwtSlider::BottomScale ) ; 00218 slider->setRange( c->getRange()->getFirst(), c->getRange()->getLast(), 00219 c->getRange()->getStep() ) ; 00220 QLabel *num = new QLabel( frame ) ; 00221 connect(slider, SIGNAL(valueChanged(double)), num, SLOT(setNum(double))); 00222 slider->setValue ( c->getValue() ) ; 00223 QHBoxLayout *layout = new QHBoxLayout() ; 00224 layout->addWidget ( label ) ; 00225 layout->addWidget ( slider ) ; 00226 layout->addWidget ( num ) ; 00227 this->inputs.append( slider ) ; 00228 return layout ; 00229 } 00230 00231 QLayout *MainWindow::getCaptureInputTXT( Capture* capture, QFrame *frame ) 00232 { 00233 CaptureTXT *c = (CaptureTXT*) capture ; 00234 QLabel *label = new QLabel( tr( c->getLabel().toAscii().data() ), frame ) ; 00235 QLineEdit *lineEdit = new QLineEdit(frame) ; 00236 lineEdit->setText( QString("%1").arg( c->getValue() ) ) ; 00237 QDoubleValidator *val = new QDoubleValidator( lineEdit ) ; 00238 lineEdit->setValidator( val ) ; 00239 QHBoxLayout *layout = new QHBoxLayout() ; 00240 layout->addWidget ( label ) ; 00241 layout->addWidget ( lineEdit ) ; 00242 this->inputs.append( lineEdit ) ; 00243 return layout ; 00244 } 00245 00246 void MainWindow::acceptCaptures () 00247 { 00248 if ( ! inputs.count() || ! currentCapts ) return ; 00249 for ( int i = 0 ; i < currentCapts->count() ; i++ ) 00250 { 00251 Capture* c = currentCapts->at( i ) ; 00252 bool setOk = false ; 00253 switch ( c->getCaptureType() ) 00254 { 00255 case Capture::CTXT : setOk = setCaptureTXT( i ) ; break ; 00256 case Capture::CGUI : setOk = setCaptureGUI( i ) ; break ; 00257 case Capture::CIMG : setOk = true ; break ; 00258 case Capture::CSEL : setOk = setCaptureSEL( i ) ; break ; 00259 case Capture::CPLOT : setOk = true ; break ; 00260 } 00261 if ( ! setOk ) return ; 00262 } 00263 currentStep->wakeUp(); 00264 currentStep = NULL ; 00265 currentCapts = NULL ; 00266 inputs.clear() ; 00267 if ( ui->splitter->widget( 1 ) ) delete ui->splitter->widget( 1 ) ; 00268 } 00269 00270 bool MainWindow::setCaptureSEL ( int order ) 00271 { 00272 QComboBox *cb = (QComboBox*) inputs.at( order ) ; 00273 CR_Select* sel = (CR_Select*)currentCapts->at( order ) ; 00274 return sel->setValue( cb->currentIndex() ) ; 00275 } 00276 00277 bool MainWindow::setCaptureGUI ( int order ) 00278 { 00279 QwtSlider *sl = (QwtSlider*) inputs.at( order ) ; 00280 CaptureGUI* c = (CaptureGUI*)currentCapts->at( order ) ; 00281 return c->setValue( sl->value() ) ; 00282 } 00283 00284 bool MainWindow::setCaptureTXT ( int order ) 00285 { 00286 QLineEdit *le = (QLineEdit*) inputs.at( order ) ; 00287 if ( ! le->isModified() ) return true ; 00288 bool convertResult ; 00289 T_MAGNITUDE v = le->text().toDouble(&convertResult) ; 00290 CaptureTXT* c = (CaptureTXT*) currentCapts->at( order ) ; 00291 if ( ! ( convertResult && c->setValue( v ) ) ) 00292 { 00293 le->setFocus() ; 00294 le->selectAll() ; 00295 QErrorMessage msg(this) ; 00296 msg.setModal( true ) ; 00297 msg.showMessage( QString( tr("The value '%1' for '%2' is not allowed") 00298 ).arg(v).arg(c->getLabel()) ) ; 00299 msg.exec() ; 00300 return false ; 00301 } 00302 return true ; 00303 } 00304 00305 void MainWindow::showReportsGUI ( Step* emisor , T_REPORT_LIST* reports ) 00306 { 00307 /* Este slot se conecta a los Steps */ 00308 emisor->sleep(); 00309 if ( ui->splitter->widget( 1 ) ) delete ui->splitter->widget( 1 ) ; 00310 QFrame *frame = new QFrame() ; 00311 QVBoxLayout *vLayout = new QVBoxLayout(frame) ; 00312 for ( int i = 0 ; i < reports->count() ; i++ ) 00313 { 00314 Report *r = reports->at( i ) ; 00315 QLayout *layout = NULL ; 00316 switch ( r->getReportType() ) 00317 { 00318 case Report::CTXT : layout = getReportOutputTXT( r, frame ) ; break ; 00319 case Report::CGUI : layout = getReportOutputGUI( r, frame ) ; break ; 00320 case Report::CIMG : layout = getCRLayoutIMG( (CR_Image*) r , frame ) ; break ; 00321 case Report::CSEL : layout = getCRLayoutSEL( (CR_Select*) r, frame, true ) ; break ; 00322 case Report::CPLOT : layout = getCRLayoutPLOT( (CR_FunctionIterator*) r , frame ) ; break ; 00323 } 00324 vLayout->addLayout( layout ) ; 00325 } 00326 QPushButton *okButton = new QPushButton( tr("Ok") , frame ) ; 00327 vLayout->addWidget( okButton ) ; 00328 QObject::connect( okButton, 00329 SIGNAL( clicked()) , 00330 this, SLOT( acceptReports() ) ) ; 00331 QPushButton *printButton = new QPushButton( tr("Print...") , frame ) ; 00332 vLayout->addWidget( printButton ) ; 00333 QObject::connect( printButton, 00334 SIGNAL( clicked()) , 00335 this, SLOT( print() ) ) ; 00336 QScrollArea *scrollArea = new QScrollArea ; 00337 scrollArea->setWidget( frame ) ; 00338 ui->splitter->addWidget( scrollArea ) ; 00339 this->currentStep = emisor ; 00340 } 00341 00342 QLayout *MainWindow::getReportOutputTXT( Report* report, QFrame *frame ) 00343 { 00344 ReportTXT *r = (ReportTXT*) report ; 00345 QLabel *label = new QLabel( tr( r->getLabel().toAscii().data() ), frame ) ; 00346 QLineEdit *lineEdit = new QLineEdit(frame) ; 00347 // Representar con 4 digitos o usar notacion exponencial: 00348 lineEdit->setText( QString("%1").arg( r->getValue() , 0 , 'g' , 4 ) ) ; 00349 lineEdit->setReadOnly( true ) ; 00350 QHBoxLayout *layout = new QHBoxLayout() ; 00351 layout->addWidget ( label ) ; 00352 layout->addWidget ( lineEdit ) ; 00353 return ( layout ) ; 00354 } 00355 00356 QLayout *MainWindow::getReportOutputGUI( Report* report, QFrame *frame ) 00357 { 00358 ReportGUI *r = (ReportGUI*) report ; 00359 QLabel *label = new QLabel( tr( r->getLabel().toAscii().data() ), frame ) ; 00360 QwtThermo *thermo = new QwtThermo( frame ) ; 00361 thermo->setOrientation ( Qt::Horizontal , QwtThermo::BottomScale ) ; 00362 thermo->setRange( r->getRange()->getFirst(), r->getRange()->getLast() ) ; 00363 thermo->setValue( r->getValue() ) ; 00364 QLabel *num = new QLabel( frame ) ; 00365 num->setNum( r->getValue() ) ; 00366 QHBoxLayout *layout = new QHBoxLayout() ; 00367 layout->addWidget ( label ) ; 00368 layout->addWidget ( thermo ) ; 00369 layout->addWidget ( num ) ; 00370 return ( layout ) ; 00371 } 00372 00373 QLayout* MainWindow::getCRLayoutIMG( CR_Image* img, QFrame *frame ) 00374 { 00375 QLabel *label = new QLabel( tr( img->getLabel().toAscii().data() ), frame ) ; 00376 QLabel *pix = new QLabel( frame ) ; 00377 QPixmap p ; 00378 if ( ! p.load( img->getSource() ) ) 00379 { 00380 QMessageBox::critical ( this, tr("Invalid Image"), 00381 QString( tr("Invalid Image file: %1") ).arg(img->getSource()) 00382 ) ; 00383 } 00384 // For now... it's only a fixed restriction, to ensure you can view it... 00385 if ( p.width() > 800 || p.height() > 600 ) 00386 p = p.scaled(800,600,Qt::KeepAspectRatio) ; 00387 pix->setPixmap( p ) ; 00388 QHBoxLayout *layout = new QHBoxLayout() ; 00389 layout->addWidget ( label ) ; 00390 layout->addWidget ( pix ) ; 00391 inputs.append( pix ) ; 00392 return ( layout ) ; 00393 } 00394 00395 QLayout* MainWindow::getCRLayoutSEL( CR_Select* sel, QFrame *frame, bool readOnly ) 00396 { 00397 QLabel *label = new QLabel( sel->getLabel() , frame ) ; 00398 QComboBox *cb = new QComboBox( frame ) ; 00399 cb->setEditable( false ) ; 00400 cb->addItems ( *sel->getOptions() ) ; 00401 cb->setCurrentIndex( sel->getValue() ) ; 00402 cb->setEnabled( ! readOnly ) ; 00403 QHBoxLayout *layout = new QHBoxLayout() ; 00404 layout->addWidget ( label ) ; 00405 layout->addWidget ( cb ) ; 00406 inputs.append( cb ) ; 00407 return ( layout ) ; 00408 } 00409 00410 #include <qwt_plot.h> 00411 #include <qwt_plot_curve.h> 00412 #include <qwt_plot_zoomer.h> 00413 //#include <qwt_plot_magnifier.h> 00414 //#include <qwt_plot_panner.h> 00415 QLayout* MainWindow::getCRLayoutPLOT( CR_FunctionIterator* fi, QFrame *frame ) 00416 { 00417 QwtDataHPlot2D* data = new QwtDataHPlot2D( fi->getIterator() , frame ) ; 00418 QwtPlot *plot = new QwtPlot(tr( fi->getLabel().toAscii().data() ), frame ) ; 00419 //QwtPlot *plot = new QwtPlot( ) ; 00420 QwtPlotCurve *curve = new QwtPlotCurve("Curve 1") ; 00421 //curve->setRenderHint(QwtPlotItem::RenderAntialiased) ; // Very Slow on zooming :( 00422 curve->setPen(QPen(Qt::blue)) ; // A colour, to make it a bit beautiful 00423 curve->setData( *data ) ; 00424 curve->attach( plot ) ; 00425 QwtPlotZoomer *zoomer = new QwtPlotZoomer( plot->canvas() ) ; 00426 //QwtPlotMagnifier *magnifier = new QwtPlotMagnifier( plot->canvas() ) ; 00427 //QwtPlotPanner *panner = new QwtPlotPanner( plot->canvas() ) ; 00428 plot->replot() ; 00429 QHBoxLayout *layout = new QHBoxLayout() ; 00430 //QLabel *label = new QLabel( tr( fi->getLabel().toAscii().data() ), frame ) ; 00431 //layout->addWidget ( label ) ; 00432 layout->addWidget ( plot ) ; 00433 inputs.append( plot ) ; // nothing to do here ;) 00434 return ( layout ) ; 00435 } 00436 00437 void MainWindow::acceptReports () 00438 { 00439 currentStep->wakeUp(); 00440 currentStep = NULL ; 00441 if ( ui->splitter->widget( 1 ) ) delete ui->splitter->widget( 1 ) ; 00442 } 00443 00444 void MainWindow::executeStep ( QListWidgetItem *item ) 00445 { 00446 if ( this->currentStep != NULL ) 00447 return ; 00448 QString name = item->text() ; 00449 /* Este slot se conecta al widget stepList (doble-click) */ 00450 if ( Step* s = core->getCurrentEnviroment()->getStep( name ) ) { 00451 //printf ("Ejecutando Step:%s\n",name.toAscii().data() ) ; 00452 s->start() ; 00453 } else { 00454 printf ("Step not found:%s\n",name.toAscii().data() ) ; 00455 } 00456 fflush( stdout ); 00457 } 00458 00459 void MainWindow::showMessage ( QString msg , int severity ) 00460 { 00461 if ( severity == 2 ) 00462 QMessageBox::critical ( this, tr("Critical Error !"), msg ) ; 00463 } 00464 00465 00466 #include <QFileDialog> 00467 void MainWindow::loadFile () 00468 { 00469 QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"), "" ) ; 00470 if ( ! fileName.isNull() ) // User was pressed "Cancel" button ? 00471 { 00472 this->clear () ; 00473 core->loadFile( fileName ) ; 00474 } 00475 } 00476 00477 #include <QPrinter> 00478 #include <QPrintDialog> 00479 #include <QPainter> 00480 void MainWindow::print () 00481 { 00482 if ( ui->splitter->widget( 1 ) == NULL ) return ; 00483 QWidget *wg = ((QScrollArea*)ui->splitter->widget( 1 ))->widget() ; 00484 QPrinter *printer = new QPrinter; 00485 QPrintDialog *printDialog = new QPrintDialog(printer, this); 00486 if (printDialog->exec() == QDialog::Accepted) { 00487 QPainter p(printer); 00488 QPixmap pm = QPixmap::grabWidget(wg); 00489 p.drawPixmap(0, 0, pm); 00490 } 00491 } 00492 00493 void MainWindow::on_action_Load_triggered() 00494 { 00495 this->loadFile() ; 00496 } 00497 00498 void MainWindow::on_actionAbout_triggered() 00499 { 00500 QMessageBox::about ( this, tr("About Hormiga"), 00501 QString("Hormiga Core %1\n%2\n%3") 00502 .arg(core->getVersion()) 00503 .arg(core->getURL()) 00504 .arg(core->getLicense())) ; 00505 } 00506 00507 #include <QDesktopServices> 00508 #include <QUrl> 00509 void MainWindow::on_action_Home_Page_triggered() 00510 { 00511 QDesktopServices::openUrl ( QUrl( core->getURL() ) ) ; 00512 } 00513 00514 void MainWindow::on_actionAbout_Qt_triggered() 00515 { 00516 QMessageBox::aboutQt( this, tr("About Qt") ) ; 00517 }