diff --git a/src/meshlab/filterthread.cpp b/src/meshlab/filterthread.cpp new file mode 100644 index 000000000..cdf8e380d --- /dev/null +++ b/src/meshlab/filterthread.cpp @@ -0,0 +1,28 @@ +#include "mainwindow.h" +#include + +#include "../common/scriptinterface.h" +#include "../common/meshlabdocumentxml.h" +#include "../common/meshlabdocumentbundler.h" +#include "filterthread.h" + +FilterThread::FilterThread(QString fname,MeshLabXMLFilterContainer *mfc, MeshDocument& md,EnvWrap& env, QObject *parent) +:QThread(parent), _fname(fname), _mfc(mfc),_md(md),_env(env) +{ +} + +FilterThread *cur=0; + +bool FilterThread::QCallBackLocal(const int pos, const char * str) +{ + /*emit cur->ThreadCB(pos,QString(str));*/ + return true; +} + +void FilterThread::run() +{ + /*assert(cur==0); + cur=this;*/ + _ret = _mfc->filterInterface->applyFilter(_fname, _md, _env, QCallBackLocal); + /*cur=0;*/ +} \ No newline at end of file diff --git a/src/meshlab/filterthread.h b/src/meshlab/filterthread.h new file mode 100644 index 000000000..6f888fdaa --- /dev/null +++ b/src/meshlab/filterthread.h @@ -0,0 +1,33 @@ +#ifndef FILTERTHREAD_H +#define FILTERTHREAD_H + +#include +#include "mainwindow.h" + +class FilterThread : public QThread +{ + Q_OBJECT +public: + explicit FilterThread(QString fname,MeshLabXMLFilterContainer *mfc, MeshDocument& md,EnvWrap& env, QObject *parent = 0); + + + MeshLabXMLFilterContainer *_mfc; + QString _fname; + MeshDocument& _md; + //vcg::CallBackPos *_qc; + EnvWrap & _env; + bool _ret; + static bool QCallBackLocal(const int pos, const char * str); + +protected: + void run(); + +signals: + void ThreadCB(const int pos, QString str); + + + public slots: + +}; + +#endif // FILTERTHREAD_H \ No newline at end of file diff --git a/src/meshlab/mainwindow.h b/src/meshlab/mainwindow.h index d592a0094..c5cc2cc5a 100644 --- a/src/meshlab/mainwindow.h +++ b/src/meshlab/mainwindow.h @@ -87,6 +87,7 @@ private slots: void endEdit(); void updateDocumentScriptBindings(); void loadAndInsertXMLPlugin(const QString& xmlpath,const QString& scriptname); + void postFilterExecution(/*MeshLabXMLFilterContainer* mfc*/); //void evaluateExpression(const Expression& exp,Value** res); public: diff --git a/src/meshlab/mainwindow_RunTime.cpp b/src/meshlab/mainwindow_RunTime.cpp index 1b00d70ea..dc9315a38 100644 --- a/src/meshlab/mainwindow_RunTime.cpp +++ b/src/meshlab/mainwindow_RunTime.cpp @@ -38,6 +38,7 @@ #include "alnParser.h" #include #include "xmlgeneratorgui.h" +#include "filterthread.h" #include "../common/scriptinterface.h" @@ -1030,10 +1031,46 @@ void MainWindow::executeFilter(QAction *action, RichParameterSet ¶ms, bool i void MainWindow::executeFilter(MeshLabXMLFilterContainer* mfc, EnvWrap& env, bool /*isPreview*/) { + if (mfc == NULL) + return; MeshLabFilterInterface *iFilter = mfc->filterInterface; bool jscode = (mfc->xmlInfo->filterScriptCode(mfc->act->text()) != ""); bool filtercpp = (iFilter != NULL) && (!jscode); QString fname = mfc->act->text(); + QString ar = mfc->xmlInfo->filterAttribute(fname,MLXMLElNames::filterArity); + MeshDocument* mmmmd = meshDoc(); + if (ar == MLXMLElNames::singleMeshArity) + meshDoc()->renderState().addMesh(meshDoc()->mm()->id(),meshDoc()->mm()->cm); + + if (ar == MLXMLElNames::fixedArity) + { + //I have to check which are the meshes requested as parameters by the filter. It's disgusting but there is not other way. + MLXMLPluginInfo::XMLMapList params = mfc->xmlInfo->filterParameters(fname); + for(int ii = 0;ii < params.size();++ii) + { + if (params[ii][MLXMLElNames::paramType] == MLXMLElNames::meshType) + { + try + { + MeshModel* tmp = env.evalMesh(params[ii][MLXMLElNames::paramName]); + if (tmp != NULL) + meshDoc()->renderState().addMesh(tmp->id(),tmp->cm); + } + catch (ExpressionHasNotThisTypeException& e) + { + QString st = "parameter " + params[ii][MLXMLElNames::paramName] + "declared of type mesh contains a not mesh value.\n"; + meshDoc()->Log.Logf(GLLogStream::FILTER,qPrintable(st)); + } + } + } + } + + //In this case I can only copy all the meshes in the document! + if (ar == MLXMLElNames::variableArity) + { + for(int ii = 0;meshDoc()->meshList.size();++ii) + meshDoc()->renderState().addMesh(meshDoc()->meshList[ii]->id(),meshDoc()->meshList[ii]->cm); + } qb->show(); if (filtercpp) iFilter->setLog(&meshDoc()->Log); @@ -1064,7 +1101,7 @@ void MainWindow::executeFilter(MeshLabXMLFilterContainer* mfc, EnvWrap& env, boo bool ret = true; qApp->setOverrideCursor(QCursor(Qt::WaitCursor)); QTime tt; tt.start(); - meshDoc()->setBusy(true); + //meshDoc()->setBusy(true); //RichParameterSet MergedEnvironment(params); //MergedEnvironment.join(currentGlobalParams); @@ -1079,12 +1116,12 @@ void MainWindow::executeFilter(MeshLabXMLFilterContainer* mfc, EnvWrap& env, boo try { bool isinter = (mfc->xmlInfo->filterAttribute(fname,MLXMLElNames::filterIsInterruptible) == "true"); - if (isinter) + /*if (isinter) { showInterruptButton(true); if (filtercpp) connect(iFilter,SIGNAL(filterUpdateRequest(const bool&,bool*)),this,SLOT(filterUpdateRequest(const bool&,bool*)),Qt::DirectConnection); - } + }*/ MLXMLPluginInfo::XMLMapList ml = mfc->xmlInfo->filterParametersExtendedInfo(fname); QString funcall = "Plugins." + mfc->xmlInfo->pluginAttribute(MLXMLElNames::pluginScriptName) + "." + mfc->xmlInfo->filterAttribute(fname,MLXMLElNames::filterScriptFunctName) + "("; if (mfc->xmlInfo->filterAttribute(fname,MLXMLElNames::filterArity) == MLXMLElNames::singleMeshArity && !jscode) @@ -1103,7 +1140,13 @@ void MainWindow::executeFilter(MeshLabXMLFilterContainer* mfc, EnvWrap& env, boo if (meshDoc() != NULL) meshDoc()->xmlhistory << funcall; if (filtercpp) - ret = iFilter->applyFilter(fname, *(meshDoc()), env, QCallBack); + { + //I'm using PM.stringXMLFilterMap[fname] instead of mfc passed like parameter because i'm sure that the first one is still alive after the function will exit. + FilterThread* ft = new FilterThread(fname,&PM.stringXMLFilterMap[fname],*(meshDoc()),env,this); + connect(ft,SIGNAL(finished()),this,SLOT(postFilterExecution())); + ft->start(); + //ret = iFilter->applyFilter(fname, *(meshDoc()), env, QCallBack); + } else { QTime t; @@ -1114,32 +1157,46 @@ void MainWindow::executeFilter(MeshLabXMLFilterContainer* mfc, EnvWrap& env, boo scriptCodeExecuted(result,t.elapsed(),""); } - if (isinter) + /*if (isinter) { showInterruptButton(false); if (filtercpp) disconnect(iFilter,SIGNAL(filterUpdateRequest(const bool&,bool*)),this,SLOT(filterUpdateRequest(const bool&,bool*))); - } + }*/ } catch(MeshLabException& e) { meshDoc()->Log.Logf(GLLogStream::SYSTEM,e.what()); ret = false; } - meshDoc()->setBusy(false); + +} + +void MainWindow::postFilterExecution() +{ + //meshDoc()->renderState().clearState(); + FilterThread* obj = qobject_cast(QObject::sender()); + if (obj == NULL) + return; + MeshLabXMLFilterContainer* mfc = obj->_mfc; + if (mfc == NULL) + return; + + QString fname = mfc->act->text(); + //meshDoc()->setBusy(false); qApp->restoreOverrideCursor(); //// (5) Apply post filter actions (e.g. recompute non updated stuff if needed) - if(ret) + if(obj->_ret) { - meshDoc()->Log.Logf(GLLogStream::SYSTEM,"Applied filter %s in %i msec",qPrintable(fname),tt.elapsed()); + //meshDoc()->Log.Logf(GLLogStream::SYSTEM,"Applied filter %s in %i msec",qPrintable(fname),tt.elapsed()); MainWindow::globalStatusBar()->showMessage("Filter successfully completed...",2000); if(GLA()) { - GLA()->setWindowModified(true); GLA()->setLastAppliedFilter(mfc->act); + GLA()->setWindowModified(true); } lastFilterAct->setText(QString("Apply filter ") + fname); lastFilterAct->setEnabled(true); @@ -1185,6 +1242,7 @@ void MainWindow::executeFilter(MeshLabXMLFilterContainer* mfc, EnvWrap& env, boo if(mvc) mvc->updateAllViewer(); + delete obj; } void MainWindow::filterUpdateRequest(const bool& redraw,bool* interrupted) @@ -2241,3 +2299,4 @@ void MainWindow::sendHistory() { plugingui->getHistory(meshDoc()->xmlhistory); } + diff --git a/src/meshlab/meshlab.pro b/src/meshlab/meshlab.pro index a8da6c37f..d5f5a06f1 100644 --- a/src/meshlab/meshlab.pro +++ b/src/meshlab/meshlab.pro @@ -26,7 +26,8 @@ HEADERS = ../common/interfaces.h \ xmlgeneratorgui.h \ $$VCGDIR/wrap/gui/trackball.h \ $$VCGDIR/wrap/gui/trackmode.h \ - $$VCGDIR/wrap/gl/trimesh.h + $$VCGDIR/wrap/gl/trimesh.h \ + filterthread.h SOURCES = main.cpp \ mainwindow_Init.cpp \ mainwindow_RunTime.cpp \ @@ -45,7 +46,8 @@ SOURCES = main.cpp \ xmlgeneratorgui.cpp \ $$VCGDIR/wrap/gui/trackball.cpp \ $$VCGDIR/wrap/gui/trackmode.cpp \ - glarea_setting.cpp + glarea_setting.cpp \ + filterthread.cpp FORMS = ui/layerDialog.ui \ ui/filterScriptDialog.ui \ diff --git a/src/meshlab/xmlstdpardialog.cpp b/src/meshlab/xmlstdpardialog.cpp index 666dba24c..ed2ae05d5 100644 --- a/src/meshlab/xmlstdpardialog.cpp +++ b/src/meshlab/xmlstdpardialog.cpp @@ -160,14 +160,13 @@ bool MeshLabXMLStdDialog::showAutoDialog(MeshLabXMLFilterContainer& mfc,PluginMa void MeshLabXMLStdDialog::applyClick() { - env.pushContext(); + //env.pushContext(); assert(curParMap.size() == stdParFrame->xmlfieldwidgets.size()); for(int ii = 0;ii < curParMap.size();++ii) { XMLMeshLabWidget* wid = stdParFrame->xmlfieldwidgets[ii]; QString exp = wid->getWidgetExpression(); env.insertExpressionBinding(curParMap[ii][MLXMLElNames::paramName],exp); - //delete exp; } ////int mask = 0;//curParSet.getDynamicFloatMask(); if(curmask) @@ -182,10 +181,10 @@ void MeshLabXMLStdDialog::applyClick() //else //{ QString nm = curmfc->act->text(); - EnvWrap wrap(env); - curmwi->executeFilter(curmfc,wrap,false); + EnvWrap* wrap = new EnvWrap(env); + curmwi->executeFilter(curmfc,*wrap,false); /*}*/ - env.popContext(); + //env.popContext(); if(curmask) meshState.create(curmask, curModel);