GenGraphForm.cpp

Go to the documentation of this file.
00001 /******************************************************************************
00002 *       SOFA, Simulation Open-Framework Architecture, version 1.0 beta 3      *
00003 *                (c) 2006-2008 MGH, INRIA, USTL, UJF, CNRS                    *
00004 *                                                                             *
00005 * This program is free software; you can redistribute it and/or modify it     *
00006 * under the terms of the GNU General Public License as published by the Free  *
00007 * Software Foundation; either version 2 of the License, or (at your option)   *
00008 * any later version.                                                          *
00009 *                                                                             *
00010 * This program is distributed in the hope that it will be useful, but WITHOUT *
00011 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
00012 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for    *
00013 * more details.                                                               *
00014 *                                                                             *
00015 * You should have received a copy of the GNU General Public License along     *
00016 * with this program; if not, write to the Free Software Foundation, Inc., 51  *
00017 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.                   *
00018 *******************************************************************************
00019 *                            SOFA :: Applications                             *
00020 *                                                                             *
00021 * Authors: M. Adam, J. Allard, B. Andre, P-J. Bensoussan, S. Cotin, C. Duriez,*
00022 * H. Delingette, F. Falipou, F. Faure, S. Fonteneau, L. Heigeas, C. Mendoza,  *
00023 * M. Nesme, P. Neumann, J-P. de la Plata Alcade, F. Poyer and F. Roy          *
00024 *                                                                             *
00025 * Contact information: contact@sofa-framework.org                             *
00026 ******************************************************************************/
00027 #include "GenGraphForm.h"
00028 #include <sofa/simulation/tree/ExportDotVisitor.h>
00029 
00030 #ifdef WIN32
00031 #include <windows.h>
00032 #endif
00033 
00034 #include <fstream>
00035 
00036 #ifdef SOFA_QT4
00037 #include "q3filedialog.h"
00038 #else
00039 #include "qlistview.h"
00040 #include "qcheckbox.h"
00041 #include "qpushbutton.h"
00042 #include "qlineedit.h"
00043 #include "qfiledialog.h"
00044 #include "qheader.h"
00045 #include "qcombobox.h"
00046 #include "qradiobutton.h"
00047 #endif
00048 
00049 namespace sofa
00050 {
00051 
00052 namespace gui
00053 {
00054 
00055 namespace qt
00056 {
00057 
00058 #ifndef SOFA_QT4
00059 typedef QListView Q3ListView;
00060 typedef QListViewItem Q3ListViewItem;
00061 typedef QFileDialog Q3FileDialog;
00062 #endif
00063 
00064 GenGraphForm::GenGraphForm()
00065 : currentTask(NULL), settingFilter(false)
00066 {
00067     // signals and slots connections
00068     connect(browseButton, SIGNAL(clicked()), this, SLOT(doBrowse()));
00069     connect(exportButton, SIGNAL(clicked()), this, SLOT(doExport()));
00070     connect(displayButton, SIGNAL(clicked()), this, SLOT(doDisplay()));
00071     connect(closeButton, SIGNAL(clicked()), this, SLOT(doClose()));
00072     connect(filename, SIGNAL(textChanged(const QString&)), this, SLOT(change()));
00073     connect(presetFilter, SIGNAL(activated(const QString&)), this, SLOT(setFilter()));
00074     connect(showNodes, SIGNAL(toggled(bool)), this, SLOT(changeFilter()));
00075     connect(showObjects, SIGNAL(toggled(bool)), this, SLOT(changeFilter()));
00076     connect(showBehaviorModels, SIGNAL(toggled(bool)), this, SLOT(changeFilter()));
00077     connect(showCollisionModels, SIGNAL(toggled(bool)), this, SLOT(changeFilter()));
00078     connect(showVisualModels, SIGNAL(toggled(bool)), this, SLOT(changeFilter()));
00079     connect(showMappings, SIGNAL(toggled(bool)), this, SLOT(changeFilter()));
00080     connect(showContext, SIGNAL(toggled(bool)), this, SLOT(changeFilter()));
00081     connect(showCollisionPipeline, SIGNAL(toggled(bool)), this, SLOT(changeFilter()));
00082     connect(showSolvers, SIGNAL(toggled(bool)), this, SLOT(changeFilter()));
00083     connect(showMechanicalStates, SIGNAL(toggled(bool)), this, SLOT(changeFilter()));
00084     connect(showForceFields, SIGNAL(toggled(bool)), this, SLOT(changeFilter()));
00085     connect(showInteractionForceFields, SIGNAL(toggled(bool)), this, SLOT(changeFilter()));
00086     connect(showConstraints, SIGNAL(toggled(bool)), this, SLOT(changeFilter()));
00087     connect(showMass, SIGNAL(toggled(bool)), this, SLOT(changeFilter()));
00088     connect(showTopology, SIGNAL(toggled(bool)), this, SLOT(changeFilter()));
00089     connect(showMechanicalMappings, SIGNAL(toggled(bool)), this, SLOT(changeFilter()));
00090 
00091     // init preset filters
00092     {
00093         std::set<std::string>& filt = presetFilters["Full Graph"];
00094         filt.insert("showNodes");
00095         filt.insert("showObjects");
00096         filt.insert("showBehaviorModels");
00097         filt.insert("showCollisionModels");
00098         filt.insert("showVisualModels");
00099         filt.insert("showMappings");
00100         filt.insert("showContext");
00101         filt.insert("showCollisionPipeline");
00102         filt.insert("showSolvers");
00103         filt.insert("showMechanicalStates");
00104         filt.insert("showForceFields");
00105         filt.insert("showInteractionForceFields");
00106         filt.insert("showConstraints");
00107         filt.insert("showMass");
00108         filt.insert("showTopology");
00109         filt.insert("showMechanicalMappings");
00110     }
00111     {
00112         std::set<std::string>& filt = presetFilters["All Objects"];
00113         filt = presetFilters["Full Graph"];
00114         filt.erase("showNodes");
00115     }
00116     {
00117         std::set<std::string>& filt = presetFilters["All Nodes"];
00118         filt.insert("showNodes");
00119     }
00120     {
00121         std::set<std::string>& filt = presetFilters["Mechanical Graph"];
00122         filt = presetFilters["Full Graph"];
00123         filt.erase("showCollisionModels");
00124         filt.erase("showVisualModels");
00125         filt.erase("showMappings");
00126         filt.erase("showCollisionPipeline");
00127     }
00128     {
00129         std::set<std::string>& filt = presetFilters["Mechanical Objects"];
00130         filt = presetFilters["Mechanical Graph"];
00131         filt.erase("showNodes");
00132     }
00133     {
00134         std::set<std::string>& filt = presetFilters["Visual Graph"];
00135         filt.insert("showNodes");
00136         filt.insert("showObjects");
00137         filt.insert("showVisualModels");
00138     }
00139     {
00140         std::set<std::string>& filt = presetFilters["Visual Objects"];
00141         filt = presetFilters["Visual Graph"];
00142         filt.erase("showNodes");
00143     }
00144     {
00145         std::set<std::string>& filt = presetFilters["Collision Graph"];
00146         filt.insert("showNodes");
00147         filt.insert("showObjects");
00148         filt.insert("showCollisionModels");
00149         filt.insert("showCollisionPipeline");
00150     }
00151     {
00152         std::set<std::string>& filt = presetFilters["Collision Objects"];
00153         filt = presetFilters["Collision Graph"];
00154         filt.erase("showNodes");
00155     }
00156     {
00157         std::set<std::string>& filt = presetFilters["Collision Response Graph"];
00158         filt.insert("showNodes");
00159         filt.insert("showObjects");
00160         //filt.insert("showBehaviorModels");
00161         filt.insert("showCollisionModels");
00162         //filt.insert("showVisualModels");
00163         //filt.insert("showMappings");
00164         //filt.insert("showContext");
00165         //filt.insert("showCollisionPipeline");
00166         filt.insert("showSolvers");
00167         filt.insert("showMechanicalStates");
00168         //filt.insert("showForceFields");
00169         filt.insert("showInteractionForceFields");
00170         filt.insert("showConstraints");
00171         //filt.insert("showMass");
00172         //filt.insert("showTopology");
00173         filt.insert("showMechanicalMappings");
00174     }
00175     {
00176         std::set<std::string>& filt = presetFilters["Collision Response Objects"];
00177         filt = presetFilters["Collision Response Graph"];
00178         filt.erase("showNodes");
00179     }
00180 
00181 }
00182 
00183 void GenGraphForm::change()
00184 {
00185     //exported = false;
00186     displayButton->setEnabled(false);
00187     if (exportButton->text() != "&Kill")
00188         exportButton->setEnabled(filename->text()!=QString(""));
00189 }
00190 
00191 void GenGraphForm::changeFilter()
00192 {
00193     displayButton->setEnabled(false);
00194     if (settingFilter) return;
00195     std::set<std::string> filt = getCurrentFilter();
00196     for (std::map<std::string,std::set<std::string> >::const_iterator it = presetFilters.begin(); it != presetFilters.end(); ++it)
00197     {
00198         if (it->second == filt)
00199         {
00200             presetFilter->setCurrentText(it->first.c_str());
00201             return;
00202         }
00203     }
00204     presetFilter->setCurrentText("");
00205 }
00206 
00207 QString removeFileExt(const QString &s)
00208 {
00209     int ext = s.findRev('.');
00210     if (ext==-1) return s;
00211     if (s.find('/', ext+1)!=-1 || s.find('\\', ext+1)!=-1)
00212         return s;
00213     return s.left(ext);
00214 }
00215 
00216 void GenGraphForm::doBrowse()
00217 {
00218     QString s = Q3FileDialog::getSaveFileName(
00219         filename->text(),
00220         "DOT Graph (*.dot)",
00221         this,
00222         "export graph file dialog",
00223         "Choose a file to save" );
00224     if (s.length()>0)
00225     {
00226         if (removeFileExt(s)==s) // no extension specified
00227             s += ".dot";
00228         filename->setText(s);
00229         change();
00230     }
00231 }
00232 
00233 void GenGraphForm::doExport()
00234 {
00235     if (!tasks.empty())
00236     {
00237         killAllTasks();
00238         return;
00239     }
00240     if (filename->text()==QString("")) return;
00241 
00242     QString dotfile = filename->text();
00243 
00244     QString basefile = removeFileExt(dotfile);
00245 
00246     if (basefile==dotfile) // no extension specified
00247         dotfile += ".dot";
00248 
00249     std::ofstream fdot;
00250     fdot.open(dotfile, std::ofstream::out | std::ofstream::trunc);
00251     if (!fdot.is_open())
00252     {
00253         qFatal("Output to %s failed.\n",(const char*)dotfile);
00254         return;
00255     }
00256     {
00257         sofa::simulation::tree::ExportDotVisitor act(&fdot);
00258         act.showNode = this->showNodes->isOn();
00259         act.showObject = this->showObjects->isOn();
00260         act.showBehaviorModel = this->showBehaviorModels->isOn();
00261         act.showCollisionModel = this->showCollisionModels->isOn();
00262         act.showVisualModel = this->showVisualModels->isOn();
00263         act.showMapping = this->showMappings->isOn();
00264         act.showContext = this->showContext->isOn();
00265         act.showCollisionPipeline = this->showCollisionPipeline->isOn();
00266         act.showSolver = this->showSolvers->isOn();
00267         act.showMechanicalState = this->showMechanicalStates->isOn();
00268         act.showForceField = this->showForceFields->isOn();
00269         act.showInteractionForceField = this->showInteractionForceFields->isOn();
00270         act.showConstraint = this->showConstraints->isOn();
00271         act.showMass = this->showMass->isOn();
00272         act.showTopology = this->showTopology->isOn();
00273         act.showMechanicalMapping = this->showMechanicalMappings->isOn();
00274         act.labelNodeName = this->labelNodeName->isOn();
00275         act.labelNodeClass = this->labelNodeClass->isOn();
00276         act.labelObjectName = this->labelObjectName->isOn();
00277         act.labelObjectClass = this->labelObjectClass->isOn();
00278         graph->executeVisitor(&act);
00279     }
00280     fdot.close();
00281 
00282     QStringList argv0;
00283     if (layoutDirV->isOn())
00284         argv0 << "dot" << "-Grankdir=TB";
00285     else if (layoutDirH->isOn())
00286         argv0 << "dot" << "-Grankdir=LR";
00287     else if (layoutSpring->isOn())
00288         argv0 << "neato";
00289     else if (layoutRadial->isOn())
00290         argv0 << "twopi";
00291 
00292     bool exp = false;
00293 
00294     exportedFile = dotfile;
00295 
00296     if (genPNG->isOn())
00297     {
00298         QStringList argv = argv0;
00299         argv << "-Tpng" << "-o" << basefile+".png";
00300         argv << dotfile;
00301         addTask(argv);
00302         if (!exp)
00303         {
00304             exp = true;
00305             exportedFile = basefile+".png";
00306         }
00307     }
00308 
00309     if (genPS->isOn())
00310     {
00311         QStringList argv = argv0;
00312         argv << "-Tps" << "-o" << basefile+".ps";
00313         argv << dotfile;
00314         addTask(argv);
00315         if (!exp)
00316         {
00317             exp = true;
00318             exportedFile = basefile+".ps";
00319         }
00320     }
00321 
00322     if (genFIG->isOn())
00323     {
00324         QStringList argv = argv0;
00325         argv << "-Tfig" << "-o" << basefile+".fig";
00326         argv << dotfile;
00327         addTask(argv);
00328         if (!exp)
00329         {
00330             exp = true;
00331             exportedFile = basefile+".fig";
00332         }
00333     }
00334 
00335     if (genSVG->isOn())
00336     {
00337         QStringList argv = argv0;
00338         argv << "-Tsvg" << "-o" << basefile+".svg";
00339         argv << dotfile;
00340         addTask(argv);
00341         if (!exp)
00342         {
00343             exp = true;
00344             exportedFile = basefile+".svg";
00345         }
00346     }
00347     //exported = true;
00348     //displayButton->setEnabled(true);
00349 }
00350 
00351 void GenGraphForm::doDisplay()
00352 {
00353     if (exportedFile==QString("")) return;
00354 
00355     std::cout << "OPEN " << (const char*)exportedFile << std::endl;
00356 
00357 #ifdef WIN32
00358     ShellExecuteA(NULL, "open", exportedFile, NULL, NULL, SW_SHOWNORMAL);
00359 #else
00360     QStringList argv;
00361     argv << "display" << exportedFile;
00362 #ifdef SOFA_QT4
00363     QString program = argv.front();
00364     argv.pop_front();
00365     //QProcess::startDetached(program, argv); //QString("start \"\"\"")+exportedFile+QString("\"\"\""));
00366     QProcess::startDetached(program, argv); //QString("start \"\"\"")+exportedFile+QString("\"\"\""));
00367 #else
00368     QProcess* p = new QProcess(argv, this);
00369     p->setCommunication(0);
00370     connect(p,SIGNAL(processExited()),p,SLOT(deleteLater()));
00371     p->start();
00372 #endif
00373 #endif
00374 }
00375 
00376 void GenGraphForm::doClose()
00377 {
00378     killAllTasks();
00379     this->close();
00380 }
00381 
00382 void GenGraphForm::setScene(sofa::simulation::tree::GNode* scene)
00383 {
00384     graph = scene;
00385 }
00386 
00387 void GenGraphForm::killAllTasks()
00388 {
00389     exportButton->setText("&Export");
00390     if (currentTask)
00391     {
00392         currentTask->kill();
00393         delete currentTask;
00394         currentTask = NULL;
00395     }
00396     tasks.clear();
00397 }
00398 
00399 void GenGraphForm::addTask(QStringList argv)
00400 {
00401     tasks.push_back(argv);
00402     if (currentTask == NULL)
00403         runTask();
00404 }
00405 
00406 void GenGraphForm::taskFinished()
00407 {
00408     std::cout << "TASK FINISHED" << std::endl;
00409     if (currentTask == NULL) return;
00410 //#ifdef SOFA_QT4
00411 //  if (currentTask->state() != QProcess::NotRunning) return;
00412 //#else
00413 //  if (currentTask->isRunning()) return;
00414 //#endif
00415     delete currentTask;
00416     currentTask = NULL;
00417     if (tasks.empty())
00418     {
00419         displayButton->setEnabled(true);
00420         exportButton->setText("&Export");
00421     }
00422     else
00423     {
00424         runTask();
00425     }
00426 }
00427 
00428 void GenGraphForm::runTask()
00429 {
00430     QStringList argv = tasks.front();
00431     tasks.pop_front();
00432     exportButton->setText("&Kill");
00433     QString cmd = argv.join(QString(" "));
00434     std::cout << "STARTING TASK " << (const char*)cmd << std::endl;
00435 #ifdef SOFA_QT4
00436     QProcess* p = new QProcess(this);
00437     QString program = argv.front();
00438     argv.pop_front();
00439     p->setReadChannelMode(QProcess::ForwardedChannels);
00440     connect(p,SIGNAL(finished(int,QProcess::ExitStatus)),this,SLOT(taskFinished()));
00441     p->start(program, argv);
00442 #else
00443     QProcess* p = new QProcess(argv, this);
00444     p->setCommunication(0);
00445     connect(p,SIGNAL(processExited()),this,SLOT(taskFinished()));
00446     p->start();
00447 #endif
00448     currentTask = p;
00449 }
00450 
00451 void GenGraphForm::setFilter()
00452 {
00453     QString fname = presetFilter->currentText();
00454     if (fname == "") return;
00455     std::string name = (const char*)fname;
00456     if (presetFilters.count(name) > 0)
00457     {
00458         const std::set<std::string> & filt = presetFilters[name];
00459         settingFilter = true;
00460         this->showNodes->setChecked(filt.find("showNodes")!=filt.end());
00461         this->showObjects->setChecked(filt.find("showObjects")!=filt.end());
00462         this->showBehaviorModels->setChecked(filt.find("showBehaviorModels")!=filt.end());
00463         this->showCollisionModels->setChecked(filt.find("showCollisionModels")!=filt.end());
00464         this->showVisualModels->setChecked(filt.find("showVisualModels")!=filt.end());
00465         this->showMappings->setChecked(filt.find("showMappings")!=filt.end());
00466         this->showContext->setChecked(filt.find("showContext")!=filt.end());
00467         this->showCollisionPipeline->setChecked(filt.find("showCollisionPipeline")!=filt.end());
00468         this->showSolvers->setChecked(filt.find("showSolvers")!=filt.end());
00469         this->showMechanicalStates->setChecked(filt.find("showMechanicalStates")!=filt.end());
00470         this->showForceFields->setChecked(filt.find("showForceFields")!=filt.end());
00471         this->showInteractionForceFields->setChecked(filt.find("showInteractionForceFields")!=filt.end());
00472         this->showConstraints->setChecked(filt.find("showConstraints")!=filt.end());
00473         this->showMass->setChecked(filt.find("showMass")!=filt.end());
00474         this->showTopology->setChecked(filt.find("showTopology")!=filt.end());
00475         this->showMechanicalMappings->setChecked(filt.find("showMechanicalMappings")!=filt.end());
00476         settingFilter = false;
00477         displayButton->setEnabled(false);
00478         presetFilter->setCurrentText(fname);
00479     }
00480     else
00481     {
00482         //if (QMessage::question(this,"Graph Preset Filters",...)
00483         presetFilters[name] = getCurrentFilter();
00484     }
00485 }
00486 
00487 std::set<std::string> GenGraphForm::getCurrentFilter()
00488 {
00489     std::set<std::string> filt;
00490     if (this->showNodes->isOn()) filt.insert("showNodes");
00491     if (this->showObjects->isOn()) filt.insert("showObjects");
00492     if (this->showBehaviorModels->isOn()) filt.insert("showBehaviorModels");
00493     if (this->showCollisionModels->isOn()) filt.insert("showCollisionModels");
00494     if (this->showVisualModels->isOn()) filt.insert("showVisualModels");
00495     if (this->showMappings->isOn()) filt.insert("showMappings");
00496     if (this->showContext->isOn()) filt.insert("showContext");
00497     if (this->showCollisionPipeline->isOn()) filt.insert("showCollisionPipeline");
00498     if (this->showSolvers->isOn()) filt.insert("showSolvers");
00499     if (this->showMechanicalStates->isOn()) filt.insert("showMechanicalStates");
00500     if (this->showForceFields->isOn()) filt.insert("showForceFields");
00501     if (this->showInteractionForceFields->isOn()) filt.insert("showInteractionForceFields");
00502     if (this->showConstraints->isOn()) filt.insert("showConstraints");
00503     if (this->showMass->isOn()) filt.insert("showMass");
00504     if (this->showTopology->isOn()) filt.insert("showTopology");
00505     if (this->showMechanicalMappings->isOn()) filt.insert("showMechanicalMappings");
00506     return filt;
00507 }
00508 
00509 } // namespace qt
00510 
00511 } // namespace gui
00512 
00513 } // namespace sofa

Generated on Sun Nov 23 02:28:35 2008 for Sofa by  doxygen 1.5.7.1