Hormiga 1.0

/var/www/hormigaproject.com.ar/files/src/mainwindow.cpp

Go to the documentation of this file.
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 }