00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
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
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
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
00161 filt.insert("showCollisionModels");
00162
00163
00164
00165
00166 filt.insert("showSolvers");
00167 filt.insert("showMechanicalStates");
00168
00169 filt.insert("showInteractionForceFields");
00170 filt.insert("showConstraints");
00171
00172
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
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)
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)
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
00348
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
00366 QProcess::startDetached(program, argv);
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
00411
00412
00413
00414
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
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 }
00510
00511 }
00512
00513 }