Main Page | Modules | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members | Related Pages

omgalgorithmmanager.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (C) 2005 by Tim Sutton*
00003  *   tim@linfiniti.com   *
00004  *                                                                         *
00005  *   This program is free software; you can redistribute it and/or modify  *
00006  *   it under the terms of the GNU General Public License as published by  *
00007  *   the Free Software Foundation; either version 2 of the License, or     *
00008  *   (at your option) any later version.                                   *
00009  *                                                                         *
00010  *   This program is distributed in the hope that it will be useful,       *
00011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00013  *   GNU General Public License for more details.                          *
00014  *                                                                         *
00015  *   You should have received a copy of the GNU General Public License     *
00016  *   along with this program; if not, write to the                         *
00017  *   Free Software Foundation, Inc.,                                       *
00018  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
00019  ***************************************************************************/
00020 
00021 //local includes
00022 #include <omgui.h>
00023 #include "omgalgorithmmanager.h"
00024 #include <omgalgorithmset.h>
00025 #include <omgalgorithmparameter.h>
00026 //qt includes
00027 #include <QDir>
00028 #include <QFile>
00029 #include <QFileDialog>
00030 #include <QFileInfo>
00031 #include <QHeaderView>
00032 #include <QMessageBox>
00033 #include <QSettings>
00034 #include <QSpinBox>
00035 #include <QDoubleSpinBox>
00036 #include <QString>
00037 #include <QTableWidget>
00038 #include <QTableWidgetItem>
00039 #include <QTextEdit>
00040 #include <QTextStream>
00041 #include <QToolTip>
00042 #include <QMessageBox>
00043 
00044 OmgAlgorithmManager::OmgAlgorithmManager(QWidget* parent, Qt::WFlags fl)
00045     : QDialog(parent,fl)
00046 {
00047   //required by Qt4 to initialise the ui
00048   setupUi(this);
00049   connect(tblAlgorithms, SIGNAL(cellClicked( int,int)), this, SLOT(cellClicked( int,int)));
00050 
00051 
00052   //Set up dynamic parameters gui
00053   mpLayout2 = new QVBoxLayout();
00054   frameParameters->setLayout(mpLayout2);
00055   mpScrollArea3 = new QScrollArea();
00056   mpLayout2->addWidget(mpScrollArea3);
00057   mpQFrame4  = new QFrame();
00058   mpScrollArea3->setWidget(mpQFrame4);
00059   mpScrollArea3->setWidgetResizable( true );
00060   mpLayout5 = new QGridLayout(mpQFrame4);
00061 
00062   
00063   //qDebug(myAlgorithmSet.toXml().toLocal8Bit());
00064   refreshAlgorithmTable();
00065 }
00066 
00067 OmgAlgorithmManager::~OmgAlgorithmManager()
00068 {
00069   //save only user profiles
00070   //mAlgorithmSet.saveAlgorithms(Omgui::userAlgorithmProfilesDirPath(),true);
00071 }
00072 
00073 void OmgAlgorithmManager::resizeEvent ( QResizeEvent * theEvent )
00074 {
00075   tblAlgorithms->setColumnWidth(1,tblAlgorithms->width());
00076 }
00077 
00078 void OmgAlgorithmManager::refreshAlgorithmTable(QString theGuid)
00079 {
00080   mAlgorithmSet.clear();
00081   mAlgorithmSet = OmgAlgorithmSet::getFromActivePlugin();
00082   mAlgorithmSet.loadAlgorithms(Omgui::userAlgorithmProfilesDirPath());
00083   //iterate through the algorithm sets adding a row for each to the table
00084   tblAlgorithms->clear();
00085   tblAlgorithms->setRowCount(0);
00086   tblAlgorithms->setColumnCount(2);
00087   int mySelectedRow=0;
00088   if (mAlgorithmSet.count() < 1)
00089   {
00090     return;
00091   }
00092 
00093   for (int i=0; i < mAlgorithmSet.count(); i++)
00094   {
00095     tblAlgorithms->insertRow(i);
00096     OmgAlgorithm myAlgorithm = mAlgorithmSet[i];
00097     if (theGuid.isEmpty())
00098     {
00099       theGuid=myAlgorithm.guid();
00100     }
00101     if (myAlgorithm.guid()==theGuid)
00102     {
00103       mySelectedRow=i;
00104     }
00105     // Add details to the new row
00106     QTableWidgetItem *mypIdItem = new QTableWidgetItem(myAlgorithm.guid());
00107     tblAlgorithms->setItem(tblAlgorithms->rowCount()-1, 0, mypIdItem);
00108     QTableWidgetItem *mypNameItem = new QTableWidgetItem(myAlgorithm.name());
00109     //display the text in red if the origin of the alg is from the adapter
00110     //rather than the users xml alg profile store
00111     OmgAlgorithm::Origin myOrigin = myAlgorithm.origin();
00112     if (myOrigin==OmgAlgorithm::USERPROFILE)
00113     {
00114       QIcon myIcon;
00115       myIcon.addFile(":/algorithmTypeUser.png");
00116       mypNameItem->setIcon(myIcon);
00117     }
00118     else if (myOrigin==OmgAlgorithm::ADAPTERPROFILE)
00119     {
00120       QIcon myIcon;
00121       myIcon.addFile(":/algorithmTypeSystem.png");
00122       mypNameItem->setIcon(myIcon);
00123     }
00124     else if (myOrigin==OmgAlgorithm::UNDEFINED)
00125     {
00126       mypNameItem->setTextColor(Qt::yellow);
00127     }
00128     tblAlgorithms->setItem(tblAlgorithms->rowCount()-1, 1, mypNameItem);
00129   }
00130   tblAlgorithms->setCurrentCell(mySelectedRow,1);
00131   QStringList headerLabels;
00132   headerLabels << "Name" <<  "Description" ;
00133   tblAlgorithms->setHorizontalHeaderLabels(headerLabels);
00134   tblAlgorithms->setColumnWidth(0,0);
00135   tblAlgorithms->setColumnWidth(1,tblAlgorithms->width());
00136   tblAlgorithms->horizontalHeader()->hide();
00137   tblAlgorithms->verticalHeader()->hide();
00138   tblAlgorithms->horizontalHeader()->setResizeMode(1,QHeaderView::Stretch);
00139   selectAlgorithm(theGuid);
00140 }
00141 
00142 void OmgAlgorithmManager::cellClicked(int theRow, int theColumn)
00143 {
00144   //note we use the alg name not the id becuase user may have customised params
00145   QString myGuid = tblAlgorithms->item(tblAlgorithms->currentRow(),0)->text();
00146   selectAlgorithm(myGuid);
00147 }
00148 void OmgAlgorithmManager::selectAlgorithm(QString theGuid)
00149 {
00150   OmgAlgorithm myAlgorithm = mAlgorithmSet.getAlgorithm(theGuid);
00151   OmgAlgorithm::Origin myOrigin = myAlgorithm.origin();
00152   bool myEnabledFlag;
00153   bool myCloneEnabledFlag=true;
00154   bool myDefaultsButtonEnabledFlag=true;
00155   //system profiles are not changeable
00156   if (myOrigin==OmgAlgorithm::ADAPTERPROFILE)
00157   {
00158     myEnabledFlag=false;
00159     myDefaultsButtonEnabledFlag=false;
00160     lblProfileNotes->setText(tr("Non-editable system profile."));
00161     lblProfileIcon->setPixmap(QPixmap(":/algorithmTypeSystem.png"));
00162   }
00163   else
00164   {
00165     myEnabledFlag=true;
00166     lblProfileNotes->setText(tr("Editable user profile."));
00167     lblProfileIcon->setPixmap(QPixmap(":/algorithmTypeUser.png"));
00168   }
00169   if (myAlgorithm.parameterCount()<1)
00170   {
00171     //dont allow cloning of algs with no parameters
00172     myCloneEnabledFlag=false;
00173     //dont show defaults button for algs with no params
00174     myDefaultsButtonEnabledFlag=false;
00175   }
00176   pbnApply->setEnabled(myEnabledFlag);
00177   pbnDelete->setEnabled(myEnabledFlag);
00178   pbnClone->setEnabled(myCloneEnabledFlag);
00179   pbnDefaults->setEnabled(myDefaultsButtonEnabledFlag);
00180   leProfileName->setText(myAlgorithm.name());
00181   leProfileName->setEnabled(myEnabledFlag);
00182   lblAlgorithm->setText(tr("Algorithm: ") + myAlgorithm.id());
00183   lblVersion->setText(myAlgorithm.version());
00184   lblAuthor->setText(myAlgorithm.author());
00185   lblCodeAuthor->setText(myAlgorithm.codeAuthor());
00186 
00187   teOverview->clear();
00188   teOverview->append(myAlgorithm.overview());
00189   teDescription->clear();
00190   teDescription->append(myAlgorithm.description());
00191   teBibliography->clear();
00192   teBibliography->append(myAlgorithm.bibliography());
00193   setParametersGui(myAlgorithm);
00194   lblParameterCount->setText(tr("Parameter Count: ") + QString::number(myAlgorithm.parameterCount()));
00195 }
00196 void OmgAlgorithmManager::on_pbnClone_clicked()
00197 {
00198   if (tblAlgorithms->currentRow() < 0) 
00199   {
00200     return;
00201   }
00202   //to clone, we get the algorithm that is currently selected
00203   //copy it and serialise it off to disk
00204   QString myGuid = tblAlgorithms->item(tblAlgorithms->currentRow(),0)->text();
00205   if (myGuid.isEmpty())
00206   {
00207     return;
00208   }
00209   OmgAlgorithm myAlgorithm = mAlgorithmSet.getAlgorithm(myGuid);
00210   QString myProfileName = myAlgorithm.name();
00211   //get a unique userfriendly name for this alg
00212   int myCount = 1;
00213   while (mAlgorithmSet.contains(myProfileName))
00214   {
00215     myProfileName = tr("Copy ") + QString::number(myCount++) + " of " + myAlgorithm.name();
00216   }
00217   myAlgorithm.setName(myProfileName);
00218   //assign this alg its own guid
00219   myAlgorithm.setGuid();
00220   //indicate that this is a user alg definition
00221   myAlgorithm.setOrigin(OmgAlgorithm::USERPROFILE);
00222   saveAlgorithm(myAlgorithm);
00223   mAlgorithmSet.addAlgorithm(myAlgorithm);
00224   refreshAlgorithmTable(myAlgorithm.guid());
00225 }
00226 void OmgAlgorithmManager::on_pbnDelete_clicked()
00227 {
00228   if (tblAlgorithms->currentRow() < 0) 
00229   {
00230     return;
00231   }
00232   
00233   if ( QMessageBox::warning(this, "openModeller Desktop",
00234                     tr("Deleting a user algorithm profile is non-reversable.\n"
00235                        "Do you really want to delete it?"),
00236                        QMessageBox::Yes | QMessageBox::No,
00237                        QMessageBox::No) == QMessageBox::No)
00238   {
00239     //user said no
00240     return;
00241   }
00242 
00243   
00244   QString myGuid = tblAlgorithms->item(tblAlgorithms->currentRow(),0)->text();
00245   if (!myGuid.isEmpty())
00246   {
00247     QFile myFile(Omgui::userAlgorithmProfilesDirPath() + QDir::separator() + myGuid + ".xml");
00248     if (!myFile.remove())
00249     {
00250       QMessageBox::warning(this, tr("openModeller Desktop"),
00251       tr("Unable to delete file \n") + myFile.fileName());
00252       //return focus to the undeleted alg
00253       refreshAlgorithmTable(myGuid);
00254     }
00255     else
00256     {
00257       //move focus to default alg
00258       refreshAlgorithmTable();
00259     }
00260   }
00261 }
00262 void OmgAlgorithmManager::on_pbnApply_clicked()
00263 {
00264   if (tblAlgorithms->currentRow() < 0) 
00265   {
00266     return;
00267   }
00268   // Get the parameters for the selected alg
00269   QString myGuid = tblAlgorithms->item(tblAlgorithms->currentRow(),0)->text();
00270   OmgAlgorithm myAlgorithm = mAlgorithmSet.getAlgorithm(myGuid);
00271   //check the name is unique if its been changed
00272   if (0!=myAlgorithm.name().compare(leProfileName->text()))
00273   {
00274     if (mAlgorithmSet.contains(leProfileName->text()))
00275     {
00276       QMessageBox::warning( this,tr("openModeller Desktop"),tr("The name you choose for your algorithm profile must be unique.\n Update it and try again."));
00277       return;
00278     }
00279     //ok user has changed the name and ther is no other alg using this name
00280     //so we can go ahead and update it
00281     myAlgorithm.setName(leProfileName->text());
00282   }
00283   QVector<OmgAlgorithmParameter> myUpdatedParameters;
00284   //Get the algorithm parameters and store in QStringList
00285   ParametersMap::Iterator myIterator;
00286   for ( myIterator = mParametersMap.begin(); myIterator != mParametersMap.end(); ++myIterator )
00287   {
00288     QString myId = myIterator.key();
00289     QString myValue= "";
00290     QString myWidgetName = myIterator.value()->objectName();
00291     if (myWidgetName.left(2)=="le")
00292     {
00293       QLineEdit * myLineEdit = (QLineEdit*) myIterator.value();
00294       myValue = myLineEdit->text();
00295     }
00296     else if (myWidgetName.left(4)=="spin")
00297     {
00298       QSpinBox * mySpinBox = (QSpinBox*) myIterator.value();
00299       myValue = QString::number(mySpinBox->value());
00300     }
00301     else if (myWidgetName.left(7)=="dblspin")
00302     {
00303       QDoubleSpinBox * mySpinBox = (QDoubleSpinBox*) myIterator.value();
00304       myValue = QString::number(mySpinBox->value());
00305     }
00306 
00307     //now store our modified parameter
00308     //to do that we just get the parameter by its id from the alg
00309     //and then overwrite its value (users can only change the value
00310     //so everything else must be the same)
00311     //then we write the modified parameter back into the alg.
00312     OmgAlgorithmParameter myParameter = myAlgorithm.parameter(myId);
00313     if (myParameter.id()!="invalid")
00314     {
00315       myParameter.setValue(myValue);
00316       myUpdatedParameters.push_back(myParameter);
00317     }
00318   }
00319   myAlgorithm.setParameters(myUpdatedParameters);
00320   //qDebug(myAlgorithm.toXml().toLocal8Bit());
00321   //true = overwrite existing
00322   mAlgorithmSet.addAlgorithm(myAlgorithm,true);
00323   saveAlgorithm(myAlgorithm);
00324   refreshAlgorithmTable(myGuid);
00325 }
00326 
00327 void OmgAlgorithmManager::setParametersGui(OmgAlgorithm &theAlgorithm)
00328 {
00329   OmgAlgorithm::Origin myOrigin = theAlgorithm.origin();
00330   bool myEnabledFlag;
00331   //system profiles are not changeable
00332   if (myOrigin==OmgAlgorithm::ADAPTERPROFILE)
00333   {
00334     myEnabledFlag=false;
00335   }
00336   else
00337   {
00338     myEnabledFlag=true;
00339   }
00340   //delete current parameter map contents
00341   //the parameters map contains widgets so we must delete each widget first
00342   //then clear the map itself
00343   ParametersMap::Iterator myParametersIterator;
00344   for ( myParametersIterator = mParametersMap.begin(); myParametersIterator != mParametersMap.end(); ++myParametersIterator )
00345   {
00346     delete myParametersIterator.value();
00347     //qDebug("Deleted widget " + myParametersIterator.key().toLocal8Bit() + " from parameters map");
00348   }
00349   mParametersMap.clear();
00350   //the default parameters map simply contains strings so we can just clear it
00351   mDefaultParametersMap.clear();
00352   //the parameter labels map once again contains widgets so we need to delete
00353   //them first
00354   ParameterLabels::Iterator myLabelIterator;
00355   for ( myLabelIterator = mLabelsMap.begin(); myLabelIterator != mLabelsMap.end(); ++myLabelIterator )
00356   {
00357     delete myLabelIterator.value();
00358   }
00359   mLabelsMap.clear();
00360   //the description labels map once again contains widgets so we need to delete
00361   //them too
00362   DescriptionLabels::Iterator myDescriptionLabelIterator;
00363   for ( myDescriptionLabelIterator = mDescriptionLabelsMap.begin(); 
00364       myDescriptionLabelIterator != mDescriptionLabelsMap.end(); 
00365       ++myDescriptionLabelIterator )
00366   {
00367     delete myDescriptionLabelIterator.value();
00368   }
00369   mDescriptionLabelsMap.clear();
00370 
00371 
00372   // clear and reinitialise the paramters layout
00373   if (mpLayout5)
00374   {
00375     delete mpLayout5;
00376   }
00377   //GridLayout within the LayoutWidget
00378   mpLayout5 = new QGridLayout(mpQFrame4); //, myRowCountInt+1,3);
00379   // Set Parameter GUI
00380   QVector<OmgAlgorithmParameter> myAlgorithmParameters = theAlgorithm.parameters();
00381   QVectorIterator<OmgAlgorithmParameter> myIterator(myAlgorithmParameters);
00382   int myRow=0;
00383   while (myIterator.hasNext())
00384   {
00385     OmgAlgorithmParameter myParameter = myIterator.next();
00386     QLabel *myLabel = new QLabel(myParameter.name() + " [" +
00387                     myParameter.minimum() +
00388                     "," +
00389                     myParameter.maximum() + 
00390                     "]");
00391 
00392     if(myParameter.type()=="Integer")
00393     {
00394       //qDebug("Parameter is an integer");
00395       QString myControlName = QString("spin"+QString(myParameter.id()));
00396       QSpinBox * mySpinBox = new QSpinBox();
00397       //system profiles are non editable
00398       mySpinBox->setEnabled(myEnabledFlag);
00399       mySpinBox->setObjectName(myControlName);
00400       mySpinBox->setRange((myParameter.minimum().toInt()), (myParameter.maximum().toInt()));
00401       if (myOrigin==OmgAlgorithm::ADAPTERPROFILE)
00402       {
00403         mySpinBox->setValue(myParameter.defaultValue().toInt());
00404       }
00405       else
00406       {
00407         mySpinBox->setValue(myParameter.value().toInt());
00408       }
00409       mySpinBox->setToolTip(myParameter.description());
00410       mpLayout5->addWidget(myLabel,myRow,0);
00411       mpLayout5->addWidget(mySpinBox,myRow,1);
00412       //
00413       // Add the widget to the map
00414       //
00415       mParametersMap[myParameter.id()] = mySpinBox;
00416       myRow++;
00417     }
00418     else if ((myParameter.type()=="Real") || (myParameter.type()=="Double"))
00419     {
00420       //qDebug("Parameter is a double");
00421       QString myControlName = QString("dblspin"+QString(myParameter.id()));
00422       QDoubleSpinBox * mySpinBox = new QDoubleSpinBox();
00423       //system profiles are non editable
00424       mySpinBox->setEnabled(myEnabledFlag);
00425       mySpinBox->setObjectName(myControlName);
00426       mySpinBox->setRange((myParameter.minimum().toFloat()), (myParameter.maximum().toFloat()));
00427       mySpinBox->setDecimals(3);
00428       mySpinBox->setSingleStep(0.5);
00429       //doesnt apply to a line edit
00430       //myLineEdit->setRange((myParameter.minimum().toInt()), (myParameter.maximum().toInt()));
00431       if (myOrigin==OmgAlgorithm::ADAPTERPROFILE)
00432       {
00433         mySpinBox->setValue(myParameter.defaultValue().toFloat());
00434       }
00435       else
00436       {
00437         mySpinBox->setValue(myParameter.value().toFloat());
00438       }
00439       mySpinBox->setToolTip(myParameter.description());
00440       mpLayout5->addWidget(myLabel,myRow,0);
00441       mpLayout5->addWidget(mySpinBox,myRow,1);
00442       //
00443       // Add the widget to the map
00444       //
00445       mParametersMap[myParameter.id()] = mySpinBox;
00446       myRow++;
00447     }
00448     mDefaultParametersMap[myParameter.id()]=QString(myParameter.defaultValue());
00449     mLabelsMap[myParameter.id()] = myLabel;
00450     //
00451     // Now draw the description label
00452     //
00453     //The description label spans two cols...
00454     //void QGridLayout::addWidget ( QWidget * widget, int fromRow, int fromColumn, int rowSpan, int columnSpan, Qt::Alignment alignment = 0 )
00455     QLabel * myDescriptionLabel = new QLabel (
00456         myParameter.description());
00457     myDescriptionLabel->setWordWrap(true);
00458     //QSizePolicy myPolicy =  myDescriptionLabel->sizePolicy();
00459     //makes labels far too big but with no clipping
00460     //myPolicy.setVerticalPolicy(QSizePolicy::MinimumExpanding);
00461     //myDescriptionLabel->setSizePolicy(myPolicy);
00462     QFontMetrics myMetrics(myDescriptionLabel->font());
00463     int myWidth = myMetrics.width(myDescriptionLabel->text());
00464     int myHeight = myMetrics.height();
00465     mpLayout5->addWidget(myDescriptionLabel,myRow,0,1,2); //1 row 2 cols spanned
00466     myHeight = ((myWidth / frameParameters->width())+1)*myHeight;
00467     myWidth = myDescriptionLabel->width() / 2;
00468     QSize mySize (myWidth,myHeight);
00469     myDescriptionLabel->setMinimumSize(mySize);
00470 
00471     mDescriptionLabelsMap[myParameter.id()] = myDescriptionLabel;
00472     ++myRow;
00473   }
00474 }
00475 
00476 void OmgAlgorithmManager::on_pbnDefaults_clicked()
00477 {
00478   ParametersMap::Iterator myIterator;
00479   for ( myIterator = mParametersMap.begin(); myIterator != mParametersMap.end(); ++myIterator )
00480   {
00481     QString myId = myIterator.key();
00482     QString myValue= "";
00483     QString myWidgetName = myIterator.value()->objectName();
00484     if (myWidgetName.left(2)=="le")
00485     {
00486       QLineEdit * myLineEdit = (QLineEdit*) myIterator.value();
00487       myLineEdit->setText(mDefaultParametersMap[myId]);
00488     }
00489     else if (myWidgetName.left(4)=="spin")
00490     {
00491       QSpinBox * mySpinBox = (QSpinBox*) myIterator.value();
00492       mySpinBox->setValue(mDefaultParametersMap[myId].toInt());
00493     }
00494     else if (myWidgetName.left(7)=="dblspin")
00495     {
00496       QDoubleSpinBox * myDoubleSpinBox = (QDoubleSpinBox*) myIterator.value();
00497       myDoubleSpinBox->setValue(mDefaultParametersMap[myId].toInt());
00498     }
00499   }
00500 }
00501 
00502 bool OmgAlgorithmManager::saveAlgorithm(OmgAlgorithm &theAlgorithm)
00503 {
00504     QString myString = theAlgorithm.toXml();
00505     //use a globally unique identifier for the file name
00506     QFile myFile(Omgui::userAlgorithmProfilesDirPath() + QDir::separator() + theAlgorithm.guid() + ".xml");
00507     if (!myFile.open(QIODevice::WriteOnly | QIODevice::Text))
00508     {
00509       return false;
00510     }
00511     QTextStream myStream(&myFile);
00512     myStream << myString;
00513     myFile.close();
00514     return true;
00515 }

Generated on Mon Apr 28 15:07:05 2008 for openModellerDesktop by  doxygen 1.4.1-20050210