diff --git a/CMakeLists.txt b/CMakeLists.txt
index d9531f46f69836c9f1981d3a572a39bfd4e1dedc..bc64947300f71bbb2cd343b88bb29c05cd16729b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -546,11 +546,10 @@ if(ENABLE_ONELAB2)
       list(APPEND EXTERNAL_LIBRARIES ${UDT_LIBRARY})
       list(APPEND EXTERNAL_INCLUDES ${UDT_INCLUDE_DIR})
     else(UDT_INCLUDE_DIR AND UDT_LIBRARY AND Threads_FOUND)
-      message(FATAL_ERROR "Unable to find UDT library")
+      message(FATAL_ERROR "Unable to find UDT library or threads")
     endif(UDT_INCLUDE_DIR AND UDT_LIBRARY AND Threads_FOUND)
   endif(ENABLE_UDT)
   set_config_option(HAVE_ONELAB2 "ONELAB2")
-  set(GMSH_SRC ${GMSH_SRC};Fltk/onelab2Group.cpp;Fltk/onelab2Group.h)
   add_subdirectory(contrib/onelab2)
   include_directories(contrib/onelab2)
 endif(ENABLE_ONELAB2)
diff --git a/Common/CommandLine.cpp b/Common/CommandLine.cpp
index 2f5613f4002e2b72a1187850f95bd828a1cf6b1c..8050d55b6f35f9d617708c881b410ef470d2f6c4 100644
--- a/Common/CommandLine.cpp
+++ b/Common/CommandLine.cpp
@@ -874,8 +874,34 @@ void GetOptions(int argc, char *argv[])
           Msg::Fatal("Missing format");
       }
       else if(!strcmp(argv[i] + 1, "listen")) {
+#ifndef HAVE_ONELAB2
         CTX::instance()->solver.listen = 1;
+#else
+        CTX::instance()->batch = 1;
         i++;
+        if(argv[i]) {
+          CTX::instance()->onelab.listen_port = atoi(argv[i]);
+        }
+        else
+          CTX::instance()->onelab.listen_port = 1148;
+        // TODO get port if one is provided
+#endif
+      }
+      else if(!strcmp(argv[i] + 1, "server")) {
+        CTX::instance()->batch = 1;
+        i++;
+        if(argv[i]){
+          std::string hostname = std::string(argv[i]);
+          size_t colon = hostname.find(':');
+          if(colon != std::string::npos) {
+            strcpy(&CTX::instance()->onelab.server_ip[0], hostname.substr(0,colon).c_str());
+            CTX::instance()->onelab.server_port = atoi(hostname.substr(colon+1).c_str());
+          }
+          else {
+            CTX::instance()->onelab.server_ip[0] = '\0';
+            CTX::instance()->onelab.server_port = 0;
+          }
+        }
       }
       else if(!strcmp(argv[i] + 1, "minterpreter")) {
         i++;
diff --git a/Common/Context.h b/Common/Context.h
index 9f10362427325c6b4b96069521bc272f673fb607..4da71f888a4d6921bdd0322d940f6d88162b008b 100644
--- a/Common/Context.h
+++ b/Common/Context.h
@@ -252,6 +252,11 @@ class CTX {
     int autoSaveDatabase, autoArchiveOutputFiles, autoMesh, autoMergeFile;
     int autoShowViews, autoShowLastStep, autoCheck, showInvisibleParameters;
   }solver;
+  // onelab options
+  struct{
+    short listen_port, server_port;
+    char server_ip[16];
+  }onelab;
   // print options
   struct{
     int fileFormat, epsQuality, epsCompress, epsPS3Shading;
diff --git a/Common/Gmsh.cpp b/Common/Gmsh.cpp
index 3d244860b02acfd6c0c3df87c371cfce8a2f8f92..af12a10ac6870aa5ea0f7e5a798197084fb2a4c2 100644
--- a/Common/Gmsh.cpp
+++ b/Common/Gmsh.cpp
@@ -46,8 +46,19 @@
 #include "FlGui.h"
 #include "graphicWindow.h"
 #include "drawContext.h"
+#if defined(HAVE_ONELAB2)
+#include "onelab2Group.h"
+#else
 #include "onelabGroup.h"
 #endif
+#endif
+
+#if defined(HAVE_ONELAB2)
+#include "OnelabDatabase.h"
+#include "NetworkUtils.h"
+
+OnelabDatabase *OnelabDatabase::_instance = NULL;
+#endif
 
 int GmshInitialize(int argc, char **argv)
 {
@@ -207,6 +218,7 @@ int GmshBatch()
       MergeFile(CTX::instance()->files[i]);
   }
 
+
 #if defined(HAVE_POST) && defined(HAVE_MESH)
   if(!CTX::instance()->bgmFileName.empty()) {
     MergePostProcessingFile(CTX::instance()->bgmFileName);
@@ -333,7 +345,6 @@ int GmshFLTK(int argc, char **argv)
     else
       Msg::Error("Invalid background mesh (no view)");
   }
-
   // listen to external solvers
   if(CTX::instance()->solver.listen){
     gmshLocalNetworkClient *c = new gmshLocalNetworkClient("Listen", "");
diff --git a/Common/GmshMessage.cpp b/Common/GmshMessage.cpp
index d94728cd0c5155ed039a6db9a4b51b7a95e47dac..88091b54e0a7efcae12ccf2e9e70ad83e700ab27 100644
--- a/Common/GmshMessage.cpp
+++ b/Common/GmshMessage.cpp
@@ -27,8 +27,11 @@
 
 #if defined(HAVE_ONELAB)
 #include "onelab.h"
-#include "gmshLocalNetworkClient.h"
 #endif
+#if defined(HAVE_ONELAB2)
+#include "OnelabDatabase.h"
+#endif
+#include "gmshLocalNetworkClient.h"
 
 #if defined(HAVE_PETSC)
 #include <petsc.h>
@@ -712,7 +715,17 @@ bool Msg::UseOnelab()
 
 void Msg::SetOnelabNumber(std::string name, double val, bool visible)
 {
-#if defined(HAVE_ONELAB)
+#ifdef HAVE_ONELAB2
+  std::vector<onelab::number> numbers;
+  OnelabDatabase::instance()->get(numbers, name);
+  if(numbers.empty()) {
+    numbers.resize(1);
+    numbers[0].setName(name);
+  }
+  numbers[0].setValue(val);
+  numbers[0].setVisible(visible);
+  OnelabDatabase::instance()->set(numbers[0], std::string("Gmsh"));
+#elif defined(HAVE_ONELAB)
   if(_onelabClient){
     std::vector<onelab::number> numbers;
     _onelabClient->get(numbers, name);
@@ -740,6 +753,9 @@ void Msg::SetOnelabString(std::string name, std::string val, bool visible)
     strings[0].setValue(val);
     strings[0].setVisible(visible);
     _onelabClient->set(strings[0]);
+#ifdef HAVE_ONELAB2
+    OnelabDatabase::instance()->set(strings[0], std::string("Gmsh"));
+#endif
   }
 #endif
 }
@@ -782,6 +798,9 @@ void Msg::InitializeOnelab(const std::string &name, const std::string &sockname)
       FILE *fp = Fopen(name.c_str(), "rb");
       if(fp){
         _onelabClient->fromFile(fp);
+#ifdef HAVE_ONELAB2
+       OnelabDatabase::instance()->fromFile(fp); 
+#endif
         fclose(fp);
       }
       else
@@ -909,7 +928,11 @@ void Msg::ExchangeOnelabParameter(const std::string &key,
   }
 
   std::vector<onelab::number> ps;
+#ifdef HAVE_ONELAB2
+  OnelabDatabase::instance()->get(ps, name);
+#else
   _onelabClient->get(ps, name);
+#endif
   bool noRange = true, noChoices = true, noLoop = true;
   bool noGraph = true, noClosed = true;
   if(ps.size()){
@@ -989,8 +1012,12 @@ void Msg::ExchangeOnelabParameter(const std::string &key,
   if(noClosed && fopt.count("Closed"))
     ps[0].setAttribute("Closed", fopt["Closed"][0] ? "1" : "0");
   _setStandardOptions(&ps[0], fopt, copt);
+#ifdef HAVE_ONELAB2
+  OnelabDatabase::instance()->set(ps[0], std::string("Gmsh"));
+#else
   _onelabClient->set(ps[0]);
 #endif
+#endif
 }
 
 void Msg::ExchangeOnelabParameter(const std::string &key,
@@ -1014,7 +1041,11 @@ void Msg::ExchangeOnelabParameter(const std::string &key,
   }
 
   std::vector<onelab::string> ps;
+#ifdef HAVE_ONELAB2
+  OnelabDatabase::instance()->get(ps, name);
+#else
   _onelabClient->get(ps, name);
+#endif
   bool noChoices = true, noClosed = true, noMultipleSelection = true;
   if(ps.size()){
     if(fopt.count("ReadOnly") && fopt["ReadOnly"][0])
@@ -1043,8 +1074,12 @@ void Msg::ExchangeOnelabParameter(const std::string &key,
   if(noMultipleSelection && copt.count("MultipleSelection"))
     ps[0].setAttribute("MultipleSelection", copt["MultipleSelection"][0]);
   _setStandardOptions(&ps[0], fopt, copt);
+#ifdef HAVE_ONELAB2
+    OnelabDatabase::instance()->set(ps[0], std::string("Gmsh"));
+#else
   _onelabClient->set(ps[0]);
 #endif
+#endif
 }
 
 void Msg::UndefineOnelabParameter(const std::string &name)
diff --git a/Common/OpenFile.cpp b/Common/OpenFile.cpp
index 728efd8be31a020b98e4a74c96c52da76d9c1ff2..b30519ccf536def053f9c4a3d07ec1df586b1ffa 100644
--- a/Common/OpenFile.cpp
+++ b/Common/OpenFile.cpp
@@ -42,7 +42,11 @@
 #if defined(HAVE_FLTK)
 #include <FL/fl_ask.H>
 #include "FlGui.h"
+#if defined(HAVE_ONELAB2)
+#include "onelab2Group.h"
+#else
 #include "onelabGroup.h"
+#endif
 #include "graphicWindow.h"
 #include "drawContext.h"
 #endif
diff --git a/Common/Options.cpp b/Common/Options.cpp
index ff05d8fc639b37436a4cda62741f839872c4e8ad..858af0a28530e4af561d794163058d90482152d9 100644
--- a/Common/Options.cpp
+++ b/Common/Options.cpp
@@ -50,7 +50,11 @@
 #include "manipWindow.h"
 #include "contextWindow.h"
 #include "clippingWindow.h"
+#ifdef HAVE_ONELAB2
+#include "onelab2Group.h"
+#else
 #include "onelabGroup.h"
+#endif
 #include "viewButton.h"
 #include "drawContextFltkCairo.h"
 #include "drawContextFltkStringTexture.h"
diff --git a/Common/onelab.h b/Common/onelab.h
index 6bd4942376c6e38513d38c0969c8986e76c3e8ea..b8f47ad690b86996e70fe95b52507585db907cc9 100644
--- a/Common/onelab.h
+++ b/Common/onelab.h
@@ -371,7 +371,7 @@ namespace onelab{
 
       return src;
     }
-    void showAttribute()
+    void showAttribute() const
     {
       std::cout << "Name: " << getName() << std::endl
         << "Label: " << getLabel() << std::endl
@@ -560,7 +560,7 @@ namespace onelab{
 
       return src;
     }
-    void showAttribute()
+    void showAttribute() const
     {
       parameter::showAttribute();
       std::cout << "Value: " << this->_value << std::endl
@@ -671,7 +671,7 @@ namespace onelab{
 
       return src;
     }
-    void showAttribute()
+    void showAttribute() const
     {
       parameter::showAttribute();
       std::cout << "Value: " << this->_value << std::endl;
@@ -813,7 +813,7 @@ namespace onelab{
       }
       return src;
     }
-    void showAttribute() {}
+    void showAttribute() const {}
 #endif
 
   };
@@ -961,7 +961,7 @@ namespace onelab{
       }
       return src;
     }
-    void showAttribute() {}
+    void showAttribute() const {}
 #endif
   };
 
diff --git a/Common/onelabUtils.cpp b/Common/onelabUtils.cpp
index 803ea54a207618c27948b98b5734b94051a6dc92..aa17c56cd801ccb00596759cf09d007c08577302 100644
--- a/Common/onelabUtils.cpp
+++ b/Common/onelabUtils.cpp
@@ -22,10 +22,63 @@
 #include "PViewOptions.h"
 #endif
 
+#if defined(HAVE_ONELAB2)
+#include "OnelabDatabase.h"
+#include "OnelabServer.h"
+#endif
+
 namespace onelabUtils {
 
   // get command line arguments for the client if "UseCommandLine" is set for
   // this client
+#ifdef HAVE_ONELAB2
+  std::vector<std::string> getCommandLine(const std::string client)
+  {
+    std::vector<std::string> args;
+    std::vector<onelab::number> n;
+    OnelabDatabase::instance()->get(n, client + "/UseCommandLine");
+    if(n.size() && n[0].getValue()){
+      std::vector<onelab::string> ps;
+      OnelabDatabase::instance()->get(ps, client + "/Action");
+      std::string action = (ps.empty() ? "" : ps[0].getValue());
+      OnelabDatabase::instance()->get(ps, client + "/1ModelName");
+      std::string modelName = (ps.empty() ? "" : ps[0].getValue());
+      OnelabDatabase::instance()->get(ps, client + "/9CheckCommand");
+      std::string checkCommand = (ps.empty() ? "" : ps[0].getValue());
+      OnelabDatabase::instance()->get(ps, client + "/9ComputeCommand");
+      std::string computeCommand = (ps.empty() ? "" : ps[0].getValue());
+      if(modelName.size()) args.push_back(" \"" + modelName + "\"");
+      if(action == "check")
+        args.push_back(" " + checkCommand) ;
+      else if(action == "compute")
+        args.push_back(" " + computeCommand);
+    }
+    return args;
+  }
+  std::string getMshFileName()
+  {
+    std::string name;
+    std::vector<onelab::string> ps;
+    OnelabDatabase::instance()->get(ps, "Gmsh/MshFileName");
+    if(ps.size()){
+      name = ps[0].getValue();
+    }
+    else{
+      name = CTX::instance()->outputFileName;
+      if(name.empty()){
+        if(CTX::instance()->mesh.fileFormat == FORMAT_AUTO)
+          name = GetDefaultFileName(FORMAT_MSH);
+        else
+          name = GetDefaultFileName(CTX::instance()->mesh.fileFormat);
+      }
+      onelab::string o("Gmsh/MshFileName", name, "Mesh name");
+      o.setKind("file");
+      o.setAttribute("Closed", "1");
+      OnelabDatabase::instance()->set(o, std::string("Gmsh"));
+    }
+  return name;
+}
+#else
   std::vector<std::string> getCommandLine(onelab::client *c)
   {
     std::vector<std::string> args;
@@ -50,9 +103,9 @@ namespace onelabUtils {
     }
     return args;
   }
-
   std::string getMshFileName(onelab::client *c)
   {
+
     std::string name;
     std::vector<onelab::string> ps;
     c->get(ps, "Gmsh/MshFileName");
@@ -83,6 +136,7 @@ namespace onelabUtils {
     */
     return name;
   }
+#endif
 
   void guessModelName(onelab::client *c)
   {
@@ -294,7 +348,86 @@ namespace onelabUtils {
   static bool _firstComputation = true;
   void setFirstComputationFlag(bool val){ _firstComputation = val; }
   bool getFirstComputationFlag(){ return _firstComputation; }
+#ifdef HAVE_ONELAB2
+  bool runGmshClient(const std::string &action, int meshAuto)
+  {
+    bool redraw = false;
+
+    // do nothing in case of a python metamodel
+    std::vector<onelab::number> pn;
+    OnelabDatabase::instance()->get(pn, "IsPyMetamodel");
+    if(pn.size() && pn[0].getValue()) return redraw;
+
+    OnelabLocalNetworkClient *c = OnelabServer::instance()->getClient("Gmsh");
+    std::cout << ((c != NULL)?"not":"ok") << std::endl;
+    if(c != NULL) return redraw; // Gmsh is remote TODO
+
+    std::string mshFileName = onelabUtils::getMshFileName();
+
+    Msg::SetGmshOnelabAction(action);
 
+    static std::string modelName = GModel::current()->getName();
+
+    if(action == "initialize"){
+      // nothing to do
+    }
+    else if(action == "reset"){
+      setFirstComputationFlag(false);
+      // nothing more to do: "check" will be called right afterwards
+    }
+    else if(action == "check"){
+      if(OnelabServer::instance()->getChanged("Gmsh") ||
+         modelName != GModel::current()->getName()){
+        // reload geometry if Gmsh parameters have been modified or
+        // if the model name has changed
+        modelName = GModel::current()->getName();
+        redraw = true;
+        OpenProject(GModel::current()->getFileName(), false);
+        OnelabServer::instance()->setChanged(true, "Gmsh");
+      }
+    }
+    else if(action == "compute"){
+      std::cout <<
+        "Gmsh getChanged is " << OnelabServer::instance()->getChanged("Gmsh") << std::endl <<
+        "modelName is " << modelName << std::endl <<
+        "current GModel is" << GModel::current()->getName() << std::endl <<
+        "stat file " << mshFileName << " is " << StatFile(mshFileName) << std::endl <<
+        "meshAuto is " << meshAuto 
+        << std::endl;
+      if(OnelabServer::instance()->getChanged("Gmsh") ||
+         modelName != GModel::current()->getName()){
+        // reload the geometry, mesh it and save the mesh if Gmsh parameters
+        // have been modified or if the model name has changed
+        modelName = GModel::current()->getName();
+        redraw = true;
+        OpenProject(GModel::current()->getFileName(), false);
+        if(getFirstComputationFlag() && !StatFile(mshFileName) && meshAuto != 2){
+          Msg::Info("Skipping mesh generation: assuming '%s' is up-to-date "
+                    "(use Solver.AutoMesh=2 to force mesh generation)",
+                    mshFileName.c_str());
+        }
+        else if(!GModel::current()->empty() && meshAuto){
+          GModel::current()->mesh(3);
+          CreateOutputFile(mshFileName, CTX::instance()->mesh.fileFormat);
+        }
+      }
+      else if(StatFile(mshFileName)){
+        // mesh+save if the mesh file does not exist
+        if(meshAuto){
+          redraw = true;
+          GModel::current()->mesh(3);
+          CreateOutputFile(mshFileName, CTX::instance()->mesh.fileFormat);
+        }
+      }
+      setFirstComputationFlag(false);
+      OnelabServer::instance()->setChanged(false, "Gmsh");
+    }
+
+    Msg::SetGmshOnelabAction("");
+
+    return redraw;
+  }
+#else
   bool runGmshClient(const std::string &action, int meshAuto)
   {
     bool redraw = false;
@@ -365,7 +498,7 @@ namespace onelabUtils {
 
     return redraw;
   }
-
+#endif
   // update x using y, giving priority to any settings in x that can be set in
   // the GUI. The value of x is only changed if y is read-only.
   double updateNumber(onelab::number &x, onelab::number &y, const bool readOnlyRange)
diff --git a/Common/onelabUtils.h b/Common/onelabUtils.h
index 9f77c34646bf90aa84297a1db06b8e5e14b367aa..246467a9b359fb940b409bad039f339f5da70066 100644
--- a/Common/onelabUtils.h
+++ b/Common/onelabUtils.h
@@ -12,9 +12,15 @@
 // onelab servers
 
 namespace onelabUtils {
+#ifdef HAVE_ONELAB2
+  std::vector<std::string> getCommandLine(const std::string client);
+  std::string getMshFileName();
+  void guessModelName(onelab::client *c); // TODO ?
+#else
   std::vector<std::string> getCommandLine(onelab::client *c);
   std::string getMshFileName(onelab::client *c);
   void guessModelName(onelab::client *c);
+#endif
   void initializeLoop(const std::string &level);
   bool incrementLoop(const std::string &level);
   std::vector<double> getRange(onelab::number &p);
diff --git a/Fltk/CMakeLists.txt b/Fltk/CMakeLists.txt
index e98342e478f1e99d4b90db0a74a448f8bdee3550..3469ee79bcac6bd44a91f92f3ece12e2406ef111 100644
--- a/Fltk/CMakeLists.txt
+++ b/Fltk/CMakeLists.txt
@@ -26,7 +26,20 @@ set(SRC
     projectionEditor.cpp
     classificationEditor.cpp
     partitionDialog.cpp
+)
+if(ENABLE_ONELAB2)
+  set(SRC
+    ${SRC}
+    onelab2Group.cpp
+  )
+else(ENALBE_ONELAB2)
+  set(SRC
+    ${SRC}
     onelabGroup.cpp
+  )
+endif(ENABLE_ONELAB2)
+set(SRC
+    ${SRC}
     inputValue.cpp inputRegion.cpp
     viewButton.cpp solverButton.cpp
     Navigator.cpp
diff --git a/Fltk/FlGui.cpp b/Fltk/FlGui.cpp
index e24ad18126b1be719220ab4f8b99136272e55616..464d09f70818202a07a135f8cbbb8cae22b8d20d 100644
--- a/Fltk/FlGui.cpp
+++ b/Fltk/FlGui.cpp
@@ -29,7 +29,11 @@ typedef unsigned long intptr_t;
 #include "clippingWindow.h"
 #include "manipWindow.h"
 #include "contextWindow.h"
+#ifdef HAVE_ONELAB2
+#include "onelab2Group.h"
+#else
 #include "onelabGroup.h"
+#endif
 #include "helpWindow.h"
 #include "colorbarWindow.h"
 #include "fileDialogs.h"
diff --git a/Fltk/gmshLocalNetworkClient.h b/Fltk/gmshLocalNetworkClient.h
index 8243598e1f0a5d678c9366c5d8696cdf01028ce1..d8b56c77cb1cb971fa15f4eff2cbf6d5ce253347 100644
--- a/Fltk/gmshLocalNetworkClient.h
+++ b/Fltk/gmshLocalNetworkClient.h
@@ -58,9 +58,15 @@ class gmshLocalNetworkClient : public onelab::localNetworkClient{
     }
     return n;
   }
+#ifdef HAVE_ONELAB2 // Useless code in onelab2
+  bool receiveMessage(gmshLocalNetworkClient *master){return true;}
+  bool run(){return true;}
+  bool kill(){return true;}
+#else
   bool receiveMessage(gmshLocalNetworkClient *master);
   bool run();
   bool kill();
+#endif
 };
 
 #endif
diff --git a/Fltk/graphicWindow.cpp b/Fltk/graphicWindow.cpp
index bff019d8530a82f5262430f151d70a23c794e217..3243f0214fe726d6fd7f2afd34c57fbedf572720 100644
--- a/Fltk/graphicWindow.cpp
+++ b/Fltk/graphicWindow.cpp
@@ -33,10 +33,6 @@ typedef unsigned long intptr_t;
 #include "fieldWindow.h"
 #include "pluginWindow.h"
 #include "helpWindow.h"
-#include "onelabGroup.h"
-#ifdef HAVE_ONELAB2
-#include "onelab2Group.h"
-#endif
 #include "gmshLocalNetworkClient.h"
 #include "fileDialogs.h"
 #include "extraDialogs.h"
@@ -3027,17 +3023,8 @@ graphicWindow::graphicWindow(bool main, int numTiles, bool detachedMenu)
   }
 
   if(main && !detachedMenu){
-#if defined(HAVE_ONELAB2)
-    // Hey Maxime, this is for you!
-    _onelab = NULL;
-    onelab2Group *_onelab2 = new onelab2Group(0, mh, twidth, height - mh - sh);
-    _tile->add(_onelab2);
-    _onelab2->resize(_tile->x(), _tile->y(), twidth, _tile->h());
-    _tile->redraw();
-#else
     _onelab = new onelabGroup(0, mh, twidth, height - mh - sh);
     _onelab->enableTreeWidgetResize(false);
-#endif
   }
   else{
     _onelab = 0;
diff --git a/Fltk/graphicWindow.h b/Fltk/graphicWindow.h
index b3cd3e94bcabda6c9c5b04b1ef583bbe5ef5359d..9ab0116ae42abffab3d9ce28edaba37de7ae58c9 100644
--- a/Fltk/graphicWindow.h
+++ b/Fltk/graphicWindow.h
@@ -19,7 +19,11 @@
 #endif
 #include <FL/Fl_Menu_Bar.H>
 #include "openglWindow.h"
+#ifdef HAVE_ONELAB2
+#include "onelab2Group.h"
+#else
 #include "onelabGroup.h"
+#endif
 
 class graphicWindow{
  private:
diff --git a/Fltk/onelab2Group.cpp b/Fltk/onelab2Group.cpp
index 981924e3343c8a9825e30a57bbbcf398da440552..2c8a6456ef19859f9837770719b1320a543846f8 100644
--- a/Fltk/onelab2Group.cpp
+++ b/Fltk/onelab2Group.cpp
@@ -9,34 +9,166 @@
 #include "inputRange.h"
 #include "outputRange.h"
 #include "inputRegion.h"
+#include "drawContext.h"
+#include "viewButton.h"
+#include "solverButton.h"
 
+#include "Gmsh.h"
+#include "onelabUtils.h"
 #include "OnelabDatabase.h"
 #include "Options.h"
 #include "Context.h"
 
-OnelabDatabase *OnelabDatabase::_instance = NULL;
+static void initializeLoops()
+{
+  onelabUtils::initializeLoop("1");
+  onelabUtils::initializeLoop("2");
+  onelabUtils::initializeLoop("3");
+
+  if(FlGui::available() && onelab::server::instance()->getChanged())
+    FlGui::instance()->rebuildTree(false);
+}
+
+static bool incrementLoops()
+{
+  bool ret = (onelabUtils::incrementLoop("3") ||
+    onelabUtils::incrementLoop("2") ||
+    onelabUtils::incrementLoop("1"));
+
+  //Define ONELAB parameter indicating whether or not in a loop
+  onelab::number n("0Metamodel/Loop",ret?1:0);
+  n.setVisible(false);
+  onelab::server::instance()->set(n);
+
+  if(FlGui::available() && onelab::server::instance()->getChanged())
+    FlGui::instance()->rebuildTree(false);
+
+  return ret;
+}
+
+static void updateGraphs()
+{
+  bool redraw = false;
+  for(int i = 0; i < 18; i++){
+    std::ostringstream tmp;
+    tmp << i;
+    bool ret = onelabUtils::updateGraph(tmp.str());
+    redraw = redraw || ret;
+  }
+  if(redraw){
+    // don't delete the widgets, as this is called in widget callbacks
+    FlGui::instance()->updateViews(true, false);
+    drawContext::global()->draw();
+  }
+}
 
 void connect_cb(Fl_Widget *w, void *arg)
 {
-  onelab2Group *obj = (onelab2Group *)arg;
-  obj->clearTree();
-  GmshNetworkClient *cli = OnelabDatabase::instance()->useAsNetworkClient(obj->getServerIP(), obj->getServerPort());
-  cli->setCallback(obj);
-  // FIXME just for debug
-  FILE *fp = fopen("/tmp/onelab.db", "rb");
-  if(fp){
-    std::cout << "Get database from onelab.db" << std::endl;
-    OnelabDatabase::instance()->fromFile(fp);
-    fclose(fp);
+  if(!arg) return;
+  onelabGroup *obj = (onelabGroup *)arg;
+  if(strcmp(w->label(), "Connect") == 0) {
+    if(!obj->useServer()) return;
+    obj->clearTree();
+    GmshNetworkClient *cli = OnelabDatabase::instance()->useAsNetworkClient(obj->getServerIP(), obj->getServerPort());
+    cli->setCallback(obj);
+    w->label("Disconnect");
+  }
+  else {
+    obj->clearTree();
+    OnelabDatabase::instance()->useAsClient()->setCallback(obj);
+    w->label("Connect");
   }
 }
 
-void onelab2_cb(Fl_Widget *w, void *data)
+void useserver_cb(Fl_Widget *w, void *arg)
+{
+  if(!arg) return;
+  Fl_Check_Button *checkbox = (Fl_Check_Button *)w;
+  onelabGroup *obj = (onelabGroup *)arg;
+  obj->useServer(checkbox->value() == 1);
+}
+
+void onelab_cb(Fl_Widget *w, void *data)
 {
   if(!data) return;
 
   std::string action((const char*)data);
-  OnelabDatabase::instance()->onelab_cb(action);
+
+  if(action == "refresh"){
+    updateGraphs();
+    return;
+  }
+
+  if(action == "stop"){
+    // TODO
+    return;
+  }
+
+  if(action == "kill"){
+    // TODO
+    return;
+  }
+
+  if(FlGui::instance()->onelab->isBusy()){
+    Msg::Info("I'm busy! Ask me that later...");
+    return;
+  }
+  Msg::Info("Try to %s", action.c_str());
+  
+  if(action == "reset"){
+    //TODO resetDb(true);
+    action = "check";
+  }
+
+  Msg::ResetErrorCounter();
+
+  //TODO FlGui::instance()->onelab->setButtonMode("", "stop");
+
+  if(action == "compute") initializeLoops();
+
+  do{
+    //OnelabDatabase::instance()->run("Gmsh", action);
+    OnelabDatabase::instance()->run(action);
+  } while(action == "compute"
+          //&& !FlGui::instance()->onelab->stop()
+          && incrementLoops());
+}
+
+
+void solver_cb(Fl_Widget *w, void *data)
+{
+  if(!FlGui::instance()->onelab) return;
+
+  int num = (intptr_t)data;
+  if(num >= 0){
+    std::string name = opt_solver_name(num, GMSH_GET, "");
+    std::cout << name << ' ';
+    std::string exe = opt_solver_executable(num, GMSH_GET, "");
+    std::string host = opt_solver_remote_login(num, GMSH_GET, "");
+    // TODO check if the client exist, if not launch it
+    OnelabDatabase::instance()->run("initialize", name);
+  }
+  if(FlGui::instance()->onelab->isBusy())
+    FlGui::instance()->onelab->show();
+  else{
+    if(CTX::instance()->launchSolverAtStartup >= 0){
+      onelab_cb(0, (void*)"reset");
+      onelabUtils::setFirstComputationFlag(true);
+    }
+    else if(num >= 0) {
+      onelab_cb(0, (void*)"check");
+    }
+    else {
+      onelab_cb(0, (void*)"refresh");
+    }
+    FlGui::instance()->onelab->updateGearMenu();
+  }
+
+  CTX::instance()->launchSolverAtStartup = -1;
+}
+void solver_batch_cb(Fl_Widget *w, void *data)
+{
+  // TODO
 }
 
 static bool getFlColor(const std::string &str, Fl_Color &c)
@@ -56,7 +188,7 @@ static bool getFlColor(const std::string &str, Fl_Color &c)
   return false;
 }
 
-onelab2Group::onelab2Group(int x, int y, int w, int h, const char *l)
+onelabGroup::onelabGroup(int x, int y, int w, int h, const char *l)
   : Fl_Group(x, y, w, h, l), _stop(false), _enableTreeWidgetResize(false)
 {
   int col = FL_BACKGROUND2_COLOR;
@@ -79,18 +211,21 @@ onelab2Group::onelab2Group(int x, int y, int w, int h, const char *l)
 
   int BB2 = BB / 2 + 4;
   _butt[0] = new Fl_Button(x + w - 3 * WB - 3 * BB2, y + h - WB - BH, BB2, BH, "Check");
-  _butt[0]->callback(onelab2_cb, (void*)"check");
+  _butt[0]->callback(onelab_cb, (void*)"check");
 
   _butt[1] = new Fl_Button(x + w - 2 * WB - 2 * BB2, y + h - WB - BH, BB2, BH, "Run");
-  _butt[1]->callback(onelab2_cb, (void*)"compute");
+  _butt[1]->callback(onelab_cb, (void*)"compute");
 
-  Fl_Check_Button *useServer = new Fl_Check_Button(x+WB, y, w-2*WB, BH, "Use a distant server"); // TODO
-  Fl_Box *ip_lbl = new Fl_Box(x+WB , y+BH, w-2*WB, BH, "Server IP address:");
-  server_ip = new Fl_Input(x+WB, y+2*BH, w-2*WB, BH, "ip");
+  Fl_Check_Button *useServer = new Fl_Check_Button(x+WB, y, w-2*WB, BH, "Use a remote server");
+  useServer->callback(useserver_cb, this);
+  /*Fl_Box *ip_lbl = */new Fl_Box(x+WB , y+BH, w-2*WB, BH, "Server IP address:");
+  server_ip = new Fl_Input(x+WB, y+2*BH, w-2*WB, BH, "");
   server_ip->value("127.0.0.1");
-  Fl_Box *port_lbl = new Fl_Box(x+WB , y+3*BH, w-2*WB, BH, "Server port:");
-  server_port = new Fl_Input(x+WB, y+4*BH, w-2*WB, BH, "port");
-  server_port->value("3456");
+  server_ip->readonly(true);
+  /*Fl_Box *port_lbl = */new Fl_Box(x+WB , y+3*BH, w-2*WB, BH, "Server port:");
+  server_port = new Fl_Input(x+WB, y+4*BH, w-2*WB, BH, "");
+  server_port->value("1148");
+  server_port->readonly(true);
   Fl_Button *connect_btn = new Fl_Button(x+WB, y+5*BH, w-2*WB, BH, "Connect");
   connect_btn->callback(connect_cb, this);
 
@@ -98,12 +233,12 @@ onelab2Group::onelab2Group(int x, int y, int w, int h, const char *l)
   _widgetLabelRatio = 0.48;
   OnelabDatabase::instance()->useAsClient()->setCallback(this);
 }
-onelab2Group::~onelab2Group()
+onelabGroup::~onelabGroup()
 {
   Fl::delete_widget(_tree);
 }
 
-void onelab2Group::clearTree(bool deleteWidgets)
+void onelabGroup::clearTree(bool deleteWidgets)
 {
   _tree->clear();
   _tree->sortorder(FL_TREE_SORT_ASCENDING);
@@ -126,10 +261,77 @@ void onelab2Group::clearTree(bool deleteWidgets)
   }
 }
 
-template <class T>
-void onelab2Group::addParameter(T &p)
+void onelabGroup::openTreeItem(const std::string &name)
+{
+  Fl_Tree_Item *n = _tree->find_item(name.c_str());
+  if(n && n->has_children()){
+    n->open();
+    _tree->redraw();
+  }
+}
+
+void onelabGroup::updateGearMenu()
+{
+  return; // TODO
+  Fl_Menu_Item* menu = (Fl_Menu_Item*)_gear->menu();
+  int values[8] = {CTX::instance()->solver.autoSaveDatabase,
+                   CTX::instance()->solver.autoArchiveOutputFiles,
+                   CTX::instance()->solver.autoCheck,
+                   CTX::instance()->solver.autoMesh,
+                   CTX::instance()->solver.autoMergeFile,
+                   CTX::instance()->solver.autoShowViews,
+                   CTX::instance()->solver.autoShowLastStep,
+                   CTX::instance()->solver.showInvisibleParameters};
+  for(int i = 0; i < 8; i++){
+    int idx = _gearOptionsStart - 1 + i;
+    if(values[i])
+      menu[idx].set();
+    else
+      menu[idx].clear();
+  }
+}
+
+void onelabGroup::rebuildSolverList()
+{
+  updateGearMenu();
+
+  std::vector<std::string> names, exes, hosts;
+  for(int i = 0; i < NUM_SOLVERS; i++){
+    if(opt_solver_name(i, GMSH_GET, "").size()){
+      names.push_back(opt_solver_name(i, GMSH_GET, ""));
+      exes.push_back(opt_solver_executable(i, GMSH_GET, ""));
+      hosts.push_back(opt_solver_remote_login(i, GMSH_GET, ""));
+    }
+  }
+  for(unsigned int i = 0; i < NUM_SOLVERS; i++){
+    if(i < names.size()){
+      onelab::server::citer it = onelab::server::instance()->findClient(names[i]);
+      if(it != onelab::server::instance()->lastClient())
+        it->second->setIndex(i);
+      opt_solver_name(i, GMSH_SET, names[i]);
+      opt_solver_executable(i, GMSH_SET, exes[i]);
+      opt_solver_remote_login(i, GMSH_SET, hosts[i]);
+    }
+    else{
+      opt_solver_name(i, GMSH_SET, "");
+      opt_solver_executable(i, GMSH_SET, "");
+      opt_solver_remote_login(i, GMSH_SET, "");
+    }
+  }
+
+  //TODO setButtonVisibility();
+  rebuildTree(true);
+}
+bool onelabGroup::useServer() {return !server_ip->readonly();}
+void onelabGroup::useServer(bool use=false)
 {
-  std::cout << "add " << p.getName() << " to the tree (visible = " << p.getVisible() << ')' << std::endl;
+  server_ip->readonly(!use);
+  server_port->readonly(!use);
+}
+
+void onelabGroup::addParameter(onelab::parameter &p)
+{
+  std::cout << "add " << p.getName() << " to the tree (visible = " << p.getVisible() << ", changed = " << p.getChanged() << ")" << std::endl;
   if(!p.getVisible() || CTX::instance()->solver.showInvisibleParameters) return;
   bool highlight = false;
   Fl_Color c;
@@ -152,7 +354,7 @@ void onelab2Group::addParameter(T &p)
   _tree->end();
   _tree->redraw();
 }
-Fl_Widget *onelab2Group::_addParameterWidget(onelab::parameter &p, int ww, int hh, Fl_Tree_Item *n, bool highlight, Fl_Color c)
+Fl_Widget *onelabGroup::_addParameterWidget(onelab::parameter &p, int ww, int hh, Fl_Tree_Item *n, bool highlight, Fl_Color c)
 {
   int type = p.getAttributeType();
   if(type == onelab::number::attributeType())
@@ -165,6 +367,47 @@ Fl_Widget *onelab2Group::_addParameterWidget(onelab::parameter &p, int ww, int h
       return _addParameterWidget(*(onelab::function *)&p, ww, hh, n, highlight, c);
   return NULL;
 }
+
+template<class T>
+static void autoCheck(const T &pold, const T &pnew, bool force=false)
+{
+  if(onelabUtils::getFirstComputationFlag()){
+    if(pold.getValue() != pnew.getValue())
+      onelabUtils::setFirstComputationFlag(false);
+  }
+
+  if((CTX::instance()->solver.autoCheck && pnew.getAttribute("AutoCheck") != "0") ||
+     pnew.getAttribute("AutoCheck") == "1"){
+    if(force || pold.getValue() != pnew.getValue())
+      onelab_cb(0, (void*)"check");
+  }
+}
+
+template <class T>
+static void setGmshOption(T &n)
+{
+  std::string opt = n.getAttribute("GmshOption");
+  if(opt.empty()) return;
+  /*if(opt == "ResetDatabase"){ // special option to reset the onelab db
+    resetDb(false);
+    FlGui::instance()->rebuildTree(false);
+    return;
+  }
+  if(opt == "Reset"){ // reset db + models except current one
+    resetDb(false);
+    for(int i = PView::list.size() - 1; i >= 0; i--)
+      delete PView::list[i];
+    for(int i = GModel::list.size() - 1; i >= 0; i--)
+      if(GModel::list[i] != GModel::current()) delete GModel::list[i];
+    FlGui::instance()->rebuildTree(false);
+    return;
+  }*/
+  std::string::size_type dot = opt.find('.');
+  if(dot == std::string::npos) return;
+  GmshSetOption(opt.substr(0, dot), opt.substr(dot + 1), n.getValue());
+  drawContext::global()->draw();
+}
+
 // callback for number
 static void onelab_number_input_range_cb(Fl_Widget *w, void *data)
 {
@@ -186,10 +429,10 @@ static void onelab_number_input_range_cb(Fl_Widget *w, void *data)
     o->doCallbackOnValues(true);
     numbers[0].setAttribute("Loop", o->loop());
     numbers[0].setAttribute("Graph", o->graph());
-    //setGmshOption(numbers[0]);
-    OnelabDatabase::instance()->set(numbers[0]);
-    //updateGraphs();
-    //autoCheck(old, numbers[0]);
+    setGmshOption(numbers[0]);
+    OnelabDatabase::instance()->set(numbers[0], std::string("localGUI"));
+    updateGraphs();
+    autoCheck(old, numbers[0]);
   }
 }
 static void onelab_number_choice_cb(Fl_Widget *w, void *data)
@@ -203,9 +446,9 @@ static void onelab_number_choice_cb(Fl_Widget *w, void *data)
     std::vector<double> choices = numbers[0].getChoices();
     onelab::number old = numbers[0];
     if(o->value() < (int)choices.size()) numbers[0].setValue(choices[o->value()]);
-    //setGmshOption(numbers[0]);
-    OnelabDatabase::instance()->set(numbers[0]);
-    //autoCheck(old, numbers[0]);
+    setGmshOption(numbers[0]);
+    OnelabDatabase::instance()->set(numbers[0], std::string("localGUI"));
+    autoCheck(old, numbers[0]);
   }
 }
 static void onelab_number_check_button_cb(Fl_Widget *w, void *data)
@@ -218,13 +461,13 @@ static void onelab_number_check_button_cb(Fl_Widget *w, void *data)
     Fl_Check_Button *o = (Fl_Check_Button*)w;
     onelab::number old = numbers[0];
     numbers[0].setValue(o->value());
-    //setGmshOption(numbers[0]);
-    OnelabDatabase::instance()->set(numbers[0]);
-    //autoCheck(old, numbers[0]);
+    setGmshOption(numbers[0]);
+    OnelabDatabase::instance()->set(numbers[0], std::string("localGUI"));
+    autoCheck(old, numbers[0]);
   }
 }
 // add a parameter number to the tree
-Fl_Widget *onelab2Group::_addParameterWidget(onelab::number &p, int ww, int hh, Fl_Tree_Item *n, bool highlight, Fl_Color c)
+Fl_Widget *onelabGroup::_addParameterWidget(onelab::number &p, int ww, int hh, Fl_Tree_Item *n, bool highlight, Fl_Color c)
 {
   char *path = strdup(getPath(n).c_str());
   _treeStrings.push_back(path);
@@ -322,12 +565,12 @@ static void onelab_string_input_choice_cb(Fl_Widget *w, void *data)
     if(choices.size())
       strings[0].setAttribute("MultipleSelection", choices);
     //setGmshOption(strings[0]);
-    OnelabDatabase::instance()->set(strings[0]);
-    //autoCheck(old, strings[0]);
+    OnelabDatabase::instance()->set(strings[0], "localGUI");
+    autoCheck(old, strings[0]);
   }
 }
 // add parameter string to tree
-Fl_Widget *onelab2Group::_addParameterWidget(onelab::string &p, int ww, int hh,
+Fl_Widget *onelabGroup::_addParameterWidget(onelab::string &p, int ww, int hh,
                                             Fl_Tree_Item *n, bool highlight, Fl_Color c)
 {
   char *path = strdup(getPath(n).c_str());
@@ -402,7 +645,7 @@ Fl_Widget *onelab2Group::_addParameterWidget(onelab::string &p, int ww, int hh,
   if(highlight) but->input()->color(c);
   return but;
 }
-Fl_Widget *onelab2Group::_addParameterWidget(onelab::region &p, int ww, int hh,
+Fl_Widget *onelabGroup::_addParameterWidget(onelab::region &p, int ww, int hh,
                                             Fl_Tree_Item *n, bool highlight, Fl_Color c)
 {
   char *path = strdup(getPath(n).c_str());
@@ -425,7 +668,7 @@ Fl_Widget *onelab2Group::_addParameterWidget(onelab::region &p, int ww, int hh,
   return but;
 }
 
-Fl_Widget *onelab2Group::_addParameterWidget(onelab::function &p, int ww, int hh,
+Fl_Widget *onelabGroup::_addParameterWidget(onelab::function &p, int ww, int hh,
                                             Fl_Tree_Item *n, bool highlight, Fl_Color c)
 {
   // non-editable value
@@ -438,15 +681,16 @@ Fl_Widget *onelab2Group::_addParameterWidget(onelab::function &p, int ww, int hh
   }
 }
 
-void onelab2Group::updateParameter(onelab::parameter &p)
+void onelabGroup::updateParameter(onelab::parameter &p)
 {
+  std::cout << "update " << p.getName() << " to the tree (visible = " << p.getVisible() << ", changed = " << p.getChanged() << ")" << std::endl;
   int type = p.getAttributeType();
   if(type == onelab::number::attributeType())
       return updateParameter(*(onelab::number *)&p);
   if(type == onelab::string::attributeType())
       return updateParameter(*(onelab::string *)&p);
 }
-void onelab2Group::updateParameter(onelab::number &p)
+void onelabGroup::updateParameter(onelab::number &p)
 {
   Fl_Tree_Item *n = _tree->find_item(p.getName().c_str());
   if(!n) {
@@ -506,7 +750,7 @@ void onelab2Group::updateParameter(onelab::number &p)
   but->loop(p.getAttribute("Loop"));
   but->graph(p.getAttribute("Graph"));
 }
-void onelab2Group::updateParameter(onelab::string &p)
+void onelabGroup::updateParameter(onelab::string &p)
 {
   Fl_Tree_Item *n = _tree->find_item(p.getName().c_str());
   if(!n) {
@@ -538,19 +782,26 @@ void onelab2Group::updateParameter(onelab::string &p)
   but->value(p.getValue().c_str());
 }
 
-void onelab2Group::removeParameter(onelab::parameter &p)
+void onelabGroup::removeParameter(onelab::parameter &p)
 {
   Fl_Tree_Item *n = _tree->find_item(p.getName().c_str());
   _tree->remove(n);
 }
 
-void onelab2Group::_computeWidths()
+void onelabGroup::_computeWidths()
 {
   _baseWidth = (int)(_tree->w() - _tree->marginleft());
   _indent = (int)(_tree->connectorwidth() / 2. + _tree->openicon()->w() / 2.);
 }
 
-std::string onelab2Group::getPath(Fl_Tree_Item *item)
+bool onelabGroup::isBusy()
+{
+  std::string s(_butt[1]->label());
+  if(s == "Run") return false;
+  return true;
+}
+
+std::string onelabGroup::getPath(Fl_Tree_Item *item)
 {
   if(!item){
     Msg::Error("No item for path");
@@ -564,3 +815,72 @@ std::string onelab2Group::getPath(Fl_Tree_Item *item)
   return std::string(path);
 }
 
+void onelabGroup::_addMenu(const std::string &path, Fl_Callback *callback, void *data)
+{
+  Fl_Tree_Item *n = _tree->add(path.c_str());
+  _tree->begin();
+  int ww = _baseWidth - (n->depth() + 1) * _indent;
+  int hh = n->labelsize() + 4;
+  Fl_Group *grp = new Fl_Group(1, 1, ww, hh);
+  Fl_Button *but = new Fl_Button(1, 1, ww, hh);
+  but->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE | FL_ALIGN_CLIP);
+  but->callback(callback, data);
+  but->box(FL_FLAT_BOX);
+  but->color(_tree->color());
+  but->selection_color(_tree->color());
+  grp->end();
+  if(!_enableTreeWidgetResize) grp->resizable(0);
+  _treeWidgets.push_back(grp);
+  std::string label = path;
+  std::string::size_type last = path.find_last_of('/');
+  if(last != std::string::npos) label = path.substr(last + 1);
+  but->copy_label(label.c_str());
+  n->widget(grp);
+  _tree->end();
+}
+
+void onelabGroup::_addSolverMenu(int num)
+{
+  std::ostringstream path;
+  path << "0Modules/Solver/Solver" << num;
+  Fl_Tree_Item *n = _tree->add(path.str().c_str());
+  int ww = _baseWidth - (n->depth() + 1) * _indent;
+  int hh = n->labelsize() + 4;
+  _tree->begin();
+  Fl_Group *grp = new Fl_Group(1, 1, ww, hh);
+  new solverButton(1, 1, ww, hh, num, _tree->color());
+  grp->end();
+  if(!_enableTreeWidgetResize) grp->resizable(0);
+  _treeWidgets.push_back(grp);
+  n->widget(grp);
+  _tree->end();
+}
+
+void onelabGroup::_addViewMenu(int num)
+{
+  std::ostringstream path;
+  path << "0Modules/Post-processing/View" << num;
+  Fl_Tree_Item *n = _tree->add(path.str().c_str());
+  int ww = _baseWidth - (n->depth() + 1) * _indent;
+  int hh = n->labelsize() + 4;
+  _tree->begin();
+  Fl_Group *grp = new Fl_Group(1, 1, ww, hh);
+  new viewButton(1, 1, ww, hh, num, _tree->color());
+  grp->end();
+  if(!_enableTreeWidgetResize) grp->resizable(0);
+  _treeWidgets.push_back(grp);
+  n->widget(grp);
+  _tree->end();
+}
+
+viewButton *onelabGroup::getViewButton(int num)
+{
+  char tmp[256];
+  sprintf(tmp, "0Modules/Post-processing/View%d", num);
+  Fl_Tree_Item *n = _tree->find_item(tmp);
+  if(n){
+    Fl_Group *grp = (Fl_Group*)n->widget();
+    return (viewButton*)grp->child(0);
+  }
+  return 0;
+}
diff --git a/Fltk/onelab2Group.h b/Fltk/onelab2Group.h
index cc36060762f71750273f9d36b474e4e33c6d1480..b212741e66e28dd0ec8df1c525456c9b949a25e8 100644
--- a/Fltk/onelab2Group.h
+++ b/Fltk/onelab2Group.h
@@ -12,7 +12,9 @@
 #include "NetworkUtils.h"
 #include "onelab.h"
 
-class onelab2Group : public Fl_Group{
+class viewButton;
+
+class onelabGroup : public Fl_Group{
 private:
   Fl_Input *server_ip, *server_port;
   Fl_Tree *_tree;
@@ -34,21 +36,53 @@ private:
   Fl_Widget *_addParameterWidget(onelab::function &p, int ww, int hh, Fl_Tree_Item *n, bool highlight, Fl_Color c);
   Fl_Widget *_addParameterWidget(onelab::region &p, int ww, int hh, Fl_Tree_Item *n, bool highlight, Fl_Color c);
   void _computeWidths();
+  void _addMenu(const std::string &path, Fl_Callback *callback, void *data);
+  void _addSolverMenu(int num);
+  void _addViewMenu(int num);
+  std::set<std::string> _getClosedGmshMenus();
+  void _addGmshMenus();
 
 public:
-  onelab2Group(int x, int y, int w, int h, const char *l=0);
-  ~onelab2Group();
+  onelabGroup(int x, int y, int w, int h, const char *l=0);
+  ~onelabGroup();
+  void updateGearMenu();
+  void rebuildSolverList();
+  void rebuildTree(bool deleteWidgets){} // useless in ONELAB2 ?
+  void enableTreeWidgetResize(bool value){ _enableTreeWidgetResize = value; }
   void clearTree(bool deleteWidgets=true);
+  void openTreeItem(const std::string &name);
   void createRemoteTree(bool keepLocal=true);
   UInt32 getServerIP() {return ip4_inet_pton(server_ip->value());}
   UInt16 getServerPort() {return (UInt16)strtoul(server_port->value(), NULL, 0);}
-  template <class T> void addParameter(T &p);
+  bool useServer();
+  void useServer(bool);
+  bool isBusy();
+  int getMinWindowWidth(){ return _minWindowWidth; }
+  int getMinWindowHeight(){ return _minWindowHeight; }
+  //template <class T> void addParameter(T &p);
+  void addParameter(onelab::parameter &p);
   void updateParameter(onelab::parameter &p);
   void updateParameter(onelab::number &p);
   void updateParameter(onelab::string &p);
   void removeParameter(onelab::parameter &p);
   std::string getPath(Fl_Tree_Item *item);
+  void insertInManuallyClosed(const std::string &path)
+  {
+    _manuallyClosed.insert(path);
+  }
+  void removeFromManuallyClosed(const std::string &path)
+  {
+    _manuallyClosed.erase(path);
+  }
+  bool isManuallyClosed(const std::string &path)
+  {
+    return _manuallyClosed.find(path) != _manuallyClosed.end();
+  }
+  viewButton *getViewButton(int num);
 };
 
 void connect_cb(Fl_Widget *w, void *arg);
+void onelab_cb(Fl_Widget *w, void *data);
+void solver_cb(Fl_Widget *w, void *data);
+void solver_batch_cb(Fl_Widget *w, void *data);
 #endif
diff --git a/Fltk/onelabGroup.cpp b/Fltk/onelabGroup.cpp
index d48af39bb720f3ce3a84735ef63bd78ebfc3c091..65c571f7bfeb5518718f73e528cad2a7c81b8c5b 100644
--- a/Fltk/onelabGroup.cpp
+++ b/Fltk/onelabGroup.cpp
@@ -931,7 +931,7 @@ void onelab_cb(Fl_Widget *w, void *data)
         // for this solver
         onelab::server::instance()->setChanged(false, c->getName());
 
-	FlGui::instance()->onelab->checkForErrors(c->getName());
+        FlGui::instance()->onelab->checkForErrors(c->getName());
       }
       if(FlGui::instance()->onelab->stop()) break;
     }
diff --git a/Fltk/viewButton.cpp b/Fltk/viewButton.cpp
index ad1c7aa0bb3053eae44d0452b39176046d2c4b7a..d7612245a707753285cc191e94d9d4ea8d2b305f 100644
--- a/Fltk/viewButton.cpp
+++ b/Fltk/viewButton.cpp
@@ -18,7 +18,11 @@
 #include "OpenFile.h"
 #include "Field.h"
 #include "OS.h"
+#ifdef HAVE_ONELAB2
+#include "onelab2Group.h"
+#else
 #include "onelabGroup.h"
+#endif
 #include "viewButton.h"
 
 static void view_toggle_cb(Fl_Widget *w, void *data)
diff --git a/Geo/GeoStringInterface.cpp b/Geo/GeoStringInterface.cpp
index 82c579034ba528b000372201f29be736df5fd04f..1c1471249f60a617dddc605e377f921fb1ab1ba4 100644
--- a/Geo/GeoStringInterface.cpp
+++ b/Geo/GeoStringInterface.cpp
@@ -23,6 +23,9 @@
 #if defined(HAVE_ONELAB)
 #include "onelab.h"
 #endif
+#if defined(HAVE_ONELAB2)
+#include "OnelabDatabase.h"
+#endif
 
 void add_infile(std::string text, std::string fileName, bool forceDestroy)
 {
@@ -139,6 +142,9 @@ void add_infile(std::string text, std::string fileName, bool forceDestroy)
 #if defined(HAVE_ONELAB)
   onelab::server::instance()->setChanged(true, "Gmsh");
 #endif
+#if defined(HAVE_ONELAB2)
+  OnelabDatabase::instance()->setChanged(true, "Gmsh");
+#endif
 }
 
 void coherence(std::string fileName)
diff --git a/contrib/onelab2/CMakeLists.txt b/contrib/onelab2/CMakeLists.txt
index ef37305050f069b82fe6372e5a3db32a420ffadb..64e683f0f0e1466120903a3de05e130b39bfd05f 100644
--- a/contrib/onelab2/CMakeLists.txt
+++ b/contrib/onelab2/CMakeLists.txt
@@ -1,10 +1,13 @@
 set(SRC
   NetworkUtils.cpp
   OnelabAttributes.cpp
+  OnelabDatabase.cpp
   OnelabProtocol.cpp
   OnelabLocalNetworkClient.cpp
   OnelabServer.cpp
-  OnelabNetworkClient.cpp)
+  OnelabNetworkClient.cpp
+  GmshNetworkClient.cpp
+  GmshLocalClient.cpp)
 
 file(GLOB HDR RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.h)
 append_gmsh_src(contrib/onelab2 "${SRC};${HDR}")
diff --git a/contrib/onelab2/GmshLocalClient.h b/contrib/onelab2/GmshLocalClient.h
index 69846e2510db92508305d8b7674680b1f48532a2..9c87fcf9af12c6fdfbd8529dcb7ace22bcd4899a 100644
--- a/contrib/onelab2/GmshLocalClient.h
+++ b/contrib/onelab2/GmshLocalClient.h
@@ -3,19 +3,33 @@
 
 #include "OnelabLocalClient.h"
 
+#ifdef HAVE_FLTK
+class onelabGroup;
+#endif
+
 class GmshLocalClient : public OnelabLocalClient
 {
 private:
-  onelab2Group *_cb_obj;
+#ifdef HAVE_FLTK
+  onelabGroup *_cb_obj;
+#endif
 public:
+#ifdef HAVE_FLTK
 	GmshLocalClient(std::string name, onelab::parameterSpace *parameterSpace)
 		: OnelabLocalClient(name, parameterSpace){
+    _cb_obj = NULL;
 	}
 	~GmshLocalClient(){}
-  void setCallback(onelab2Group *cb) {_cb_obj = cb;}
-	void onNewParameter(onelab::parameter *p){_cb_obj->addParameter(*p);}
-  void onUpdateParameter(onelab::parameter *p){_cb_obj->updateParameter(*p);}
-  void onRemoveParameter(onelab::parameter *p){_cb_obj->removeParameter(*p);}
+  void setCallback(onelabGroup *cb);
+	void onNewParameter(onelab::parameter *p);
+  void onUpdateParameter(onelab::parameter *p);
+  void onRemoveParameter(onelab::parameter *p);
+#else
+	GmshLocalClient(std::string name, onelab::parameterSpace *parameterSpace)
+		: OnelabLocalClient(name, parameterSpace){}
+#endif
+
+  void run(std::string action);
 };
 
 #endif
diff --git a/contrib/onelab2/GmshNetworkClient.h b/contrib/onelab2/GmshNetworkClient.h
index 90b80687bdd95a3b0bc0bae22d13ad3b28ad3690..3ba86cd6babdd3b9fd10bd3a621fafb5495d731a 100644
--- a/contrib/onelab2/GmshNetworkClient.h
+++ b/contrib/onelab2/GmshNetworkClient.h
@@ -8,20 +8,28 @@
 #include "OnelabNetworkClient.h"
 #include "OnelabProtocol.h"
 
-class onelab2Group;
+#ifdef HAVE_FLTK
+class onelabGroup;
+#endif
 
 class GmshNetworkClient : public OnelabNetworkClient
 {
 private:
-  onelab2Group *_cb_obj;
+#ifdef HAVE_FLTK
+  onelabGroup *_cb_obj;
+#endif
 public:
+#ifdef HAVE_FLTK
+	GmshNetworkClient(std::string name) : OnelabNetworkClient(name) {_cb_obj=NULL;}
+	GmshNetworkClient(std::string name, unsigned int ip, unsigned short port) : OnelabNetworkClient(name, ip, port) {_cb_obj =NULL;}
+  void setCallback(onelabGroup *cb);
+	void onNewParameter(onelab::parameter *p);
+  void onUpdateParameter(onelab::parameter *p);
+  void onRemoveParameter(onelab::parameter *p);
+#else
 	GmshNetworkClient(std::string name) : OnelabNetworkClient(name) {}
 	GmshNetworkClient(std::string name, unsigned int ip, unsigned short port) : OnelabNetworkClient(name, ip, port) {}
-	~GmshNetworkClient() {}
-  void setCallback(onelab2Group *cb) {_cb_obj = cb;}
-	void onNewParameter(onelab::parameter *p){_cb_obj->addParameter(*p);}
-  void onUpdateParameter(onelab::parameter *p){_cb_obj->updateParameter(*p);}
-  void onRemoveParameter(onelab::parameter *p){_cb_obj->removeParameter(*p);}
+#endif
 };
 
 #endif
diff --git a/contrib/onelab2/NetworkUtils.cpp b/contrib/onelab2/NetworkUtils.cpp
index 71cbe9eb63ee9b19320cc590e20bcc821f6750a4..0aec45a55fe57270190d311d790264919442ebdf 100644
--- a/contrib/onelab2/NetworkUtils.cpp
+++ b/contrib/onelab2/NetworkUtils.cpp
@@ -106,7 +106,6 @@ int ip4_socket_send(Socket fd, UInt8 *src, int length, IPv4 dst)
 
 	// TODO handle error (length != sent) for ??? and (sent < 0) for local error
   std::cout << "ip: send " << sent << "/" << length << "bytes to " << ip4_inet_ntop(dst.address)<< ':' << dst.port << std::endl;
-  //usleep(100000);
 	return (int)sent;
 }
 
diff --git a/contrib/onelab2/OnelabAttributes.cpp b/contrib/onelab2/OnelabAttributes.cpp
index 4910149be88caef69f27a6edb0e277bfa45a038a..c6d67b5cf5b769b0636ed55168ff19f075314ea1 100644
--- a/contrib/onelab2/OnelabAttributes.cpp
+++ b/contrib/onelab2/OnelabAttributes.cpp
@@ -18,7 +18,7 @@ UInt8 *OnelabAttrStart::parseAttribute(UInt8 *src, UInt32 length)
 
 	return src+length;
 }
-void OnelabAttrStart::showAttribute()
+void OnelabAttrStart::showAttribute() const
 {
 	std::cout << "\033[1m" << "Attribute start:"<< getAttributeType() << "\033[0m"<< std::endl
 		<< "name:   " << _name << std::endl;
@@ -43,7 +43,7 @@ UInt8 *OnelabAttrParameterQuery::parseAttribute(UInt8 *src, UInt32 length)
 
 	return src+length;
 }
-void OnelabAttrParameterQuery::showAttribute()
+void OnelabAttrParameterQuery::showAttribute() const
 {
 	std::cout << "\033[1m" << "Attribute parameter query:"<< getAttributeType() << "\033[0m"<< std::endl
 		<< "type:   " << this->_ptype << std::endl
@@ -72,14 +72,14 @@ UInt8 *OnelabAttrMessage::parseAttribute(UInt8 *src, UInt32 length)
 
 	return src;
 }
-void OnelabAttrMessage::showAttribute()
+void OnelabAttrMessage::showAttribute() const
 {
 	std::cout << "Attribute message:" << std::endl
 		<< "Level:   " << _level << std::endl
 		<< "Message: " << _message << std::endl;
 }
 
-UInt8 *OnelabAttrAction::encodeAttibute(UInt8 *dst)
+UInt8 *OnelabAttrAction::encodeAttribute(UInt8 *dst)
 {
   dst = encode(dst, getAttributeType());
   dst = encode(dst, getAttributeLength());
@@ -90,7 +90,7 @@ UInt8 *OnelabAttrAction::encodeAttibute(UInt8 *dst)
   return dst;
 }
 
-UInt8 *OnelabAttrAction::parseAttibute(UInt8 *src, UInt32 length)
+UInt8 *OnelabAttrAction::parseAttribute(UInt8 *src, UInt32 length)
 {
   _client.assign((char *)src);
   src += _client.size()+1;
@@ -99,6 +99,13 @@ UInt8 *OnelabAttrAction::parseAttibute(UInt8 *src, UInt32 length)
   return src;
 }
 
+void OnelabAttrAction::showAttribute() const
+{
+	std::cout << "\033[1m" << "Attribute action:"<< getAttributeType() << "\033[0m"<< std::endl
+		<< "client (target):  " << _client << std::endl
+		<< "action:           " << _action << std::endl;
+}
+
 UInt8 *OnelabAttrFileQuery::encodeAttribute(UInt8 *dst)
 {
 	dst = encode(dst, getAttributeType());
@@ -126,6 +133,13 @@ void OnelabAttrFileQuery::setFilename(const std::string name)
   _length = name.size();
   _name = strndup(name.c_str(), _length);
 }
+void OnelabAttrFileQuery::showAttribute() const
+{
+	std::cout << "\033[1m" << "Attribute file query:"<< getAttributeType() << "\033[0m"<< std::endl
+		<< "client (file):  " << _client << std::endl
+		<< "file:           " << _name << std::endl;
+}
+
 
 UInt8 *OnelabAttrFile::encodeAttribute(UInt8 *dst)
 {
@@ -145,3 +159,8 @@ UInt8 *OnelabAttrFile::parseAttribute(UInt8 *src, UInt32 length)
   _name = strndup((char *)src, length-4);
   return  src+length-4;
 }
+void OnelabAttrFile::showAttribute() const
+{
+	std::cout << "\033[1m" << "Attribute file:"<< getAttributeType() << "\033[0m"<< std::endl
+		<< "file:           " << _name << std::endl;
+}
diff --git a/contrib/onelab2/OnelabAttributes.h b/contrib/onelab2/OnelabAttributes.h
index b7dac34e1cb11f79daef882e4ab88f52a5913b29..7a8b7fe6b5a9cc1dde61ad3508d15c8f17379611 100644
--- a/contrib/onelab2/OnelabAttributes.h
+++ b/contrib/onelab2/OnelabAttributes.h
@@ -25,7 +25,7 @@ public:
 
 	virtual UInt8 *encodeAttribute(UInt8 *dst) = 0;
 	virtual UInt8 *parseAttribute(UInt8 *src, UInt32 length) = 0;
-	virtual void showAttribute() = 0;
+	virtual void showAttribute() const = 0;
 
 	virtual inline UInt16 getAttributeType() const = 0;
 	virtual inline UInt16 getAttributeLength() const = 0;
@@ -61,7 +61,7 @@ public:
 	~OnelabAttrStart(){}
 	UInt8 *encodeAttribute(UInt8 *dst);
 	UInt8 *parseAttribute(UInt8 *src, UInt32 length);
-	void showAttribute();
+	void showAttribute() const;
 
 	static UInt16 attributeType() {return 0x04;}
 	inline UInt16 getAttributeType() const {return this->attributeType();}
@@ -81,7 +81,7 @@ public:
 	~OnelabAttrParameterQuery() {}
 	UInt8 *encodeAttribute(UInt8 *buff);
 	UInt8 *parseAttribute(UInt8 *buff, UInt32 length);
-	void showAttribute();
+	void showAttribute() const;
 
 	static UInt16 attributeType() {return 0x05;}
 	inline UInt16 getAttributeType() const {return this->attributeType();}
@@ -94,17 +94,17 @@ public:
 class OnelabAttrMessage : public OnelabAttr
 {
 private:
-	UInt8 _level;
-	UInt8 *_message;
+	UInt8 *_message = NULL;
 	UInt16 _messageLength;
+	UInt8 _level;
 	
 public:
-	OnelabAttrMessage() {this->_message = NULL; this->_level = 0;}
-	OnelabAttrMessage(std::string message, const int level=OnelabAttrMessage::Debug) {setMessage(message, level);}
+	OnelabAttrMessage() : _message(NULL), _messageLength(0), _level(0) {}
+	OnelabAttrMessage(std::string message, const int level=OnelabAttrMessage::Debug) : _message(NULL){setMessage(message, level);}
 	~OnelabAttrMessage(){if(_message != NULL) free(_message);};
 	UInt8 *encodeAttribute(UInt8 *dst);
 	UInt8 *parseAttribute(UInt8 *src, UInt32 length);
-	void showAttribute();
+	void showAttribute() const;
 
 	static UInt16 attributeType() {return 0x0A;}
 	inline UInt16 getAttributeType() const {return this->attributeType();}
@@ -134,18 +134,19 @@ class OnelabAttrAction : public OnelabAttr
 private:
   std::string _action;
   std::string _client;
+
 public:
   OnelabAttrAction() : _action(""), _client("") {}
   OnelabAttrAction(std::string action, std::string client) : _action(action), _client(client) {}
   ~OnelabAttrAction() {}
 
-  static UInt16 attributeType() {return 0x10;}
-  inline UInt16 getAttibuteType() const {return attributeType();}
-  inline UInt16 getAttibuteLength() const {return _client.size()+1+_action.size();}
+  UInt8 *encodeAttribute(UInt8 *dst);
+  UInt8 *parseAttribute(UInt8 *src, UInt32 lenght);
+  void showAttribute() const;
 
-  UInt8 *encodeAttibute(UInt8 *dst);
-  UInt8 *parseAttibute(UInt8 *src, UInt32 lenght);
-  void showAttribute() {}
+  static UInt16 attributeType() {return 0x10;}
+  inline UInt16 getAttributeType() const {return attributeType();}
+  inline UInt16 getAttributeLength() const {return _client.size()+1+_action.size();}
 
   void setAction(std::string action) {_action = action;}
   void setClient(std::string client) {_client = client;}
@@ -166,7 +167,7 @@ public:
   ~OnelabAttrFileQuery() {if(_name != NULL) free(_name);}
   UInt8 *encodeAttribute(UInt8 *dst);
   UInt8 *parseAttribute(UInt8 *src, UInt32 length);
-  void showAttribute(){}
+  void showAttribute() const;
 
   static UInt16 attributeType() {return 0x0B;}
   inline UInt16 getAttributeType() const {return attributeType();}
@@ -190,7 +191,7 @@ public:
   ~OnelabAttrFile() {if(_name != NULL) free(_name);}
   UInt8 *encodeAttribute(UInt8 *dst);
   UInt8 *parseAttribute(UInt8 *src, UInt32 length);
-  void showAttribute(){}
+  void showAttribute() const;
 
   static UInt16 attributeType() {return 0x0C;}
   inline UInt16 getAttributeType() const {return attributeType();}
diff --git a/contrib/onelab2/OnelabDatabase.h b/contrib/onelab2/OnelabDatabase.h
index 906717f8cd6438e6292c6b09666e82789a5cc322..467e54e3a4061f3852c0bd36f61c3b59d79da6d1 100644
--- a/contrib/onelab2/OnelabDatabase.h
+++ b/contrib/onelab2/OnelabDatabase.h
@@ -1,12 +1,15 @@
+#ifndef _ONELABDATABASE_H_
+#define _ONELABDATABASE_H_
+#endif
 #include <signal.h>
 #include <stdio.h>
 
 #include "GmshMessage.h"
+#include "onelabUtils.h"
 #include "OnelabServer.h"
+#include "VirtualClient.h"
 #include "GmshNetworkClient.h"
 #include "GmshLocalClient.h"
-#include "onelabUtils.h"
-
 
 #ifndef WIN32
 void *OnelabDatabase_listen(void *arg);
@@ -16,8 +19,6 @@ DWORD WINAPI OnelabDatabase_listen(LPVOID arg);
 DWORD WINAPI OnelabDatabase_server(void *arg);
 #endif
 
-OnelabServer *OnelabServer::_server = NULL;
-
 // OnelabDatabase is a singleton that get/set/... parameters from server/clients
 class OnelabDatabase {
 private:
@@ -27,8 +28,10 @@ private:
 #else
   HANDLER _listenThread, _serverThread;
 #endif
+  bool _haveToStop;
+  std::string _action;
   GmshNetworkClient *_client;
-  GmshLocalClient *_localClient;
+  GmshLocalClient *_localGUI, *_localGmsh;
   void _clear() {
 #ifndef WIN32
     // TODO send message to thread to exit the thread
@@ -37,14 +40,19 @@ private:
 #else
     // TODO
 #endif
-    if(_client) delete _client;
-    if(_localClient) delete _localClient;
-    _client = NULL; _localClient = NULL;
+    if(_client) {
+      _client->disconnect();
+      delete _client;
+    }
+    if(_localGUI) delete _localGUI;
+    if(_localGmsh) delete _localGmsh;
+    _client = NULL; _localGUI = _localGmsh = NULL;
   }
 
 public:
   OnelabDatabase() {
-    _localClient = NULL; _client = NULL;
+    _localGUI = NULL; _client = NULL; _localGmsh = NULL;
+    _action = ""; _haveToStop = false;
   }
   static OnelabDatabase *instance() {
     if(!_instance) _instance = new OnelabDatabase;
@@ -56,33 +64,55 @@ public:
 
     OnelabServer::instance(0x7F000001, 0);
     //OnelabServer::instance(0, 0);
-    _localClient = new GmshLocalClient("localGUI", OnelabServer::instance()->getParameterSpace());
-    OnelabServer::instance()->addClient(_localClient); // TODO remove from server in _clear()
+    _localGUI = new GmshLocalClient("localGUI", OnelabServer::instance()->getParameterSpace());
+    _localGmsh = new GmshLocalClient("Gmsh", OnelabServer::instance()->getParameterSpace());
+    OnelabServer::instance()->addClient(_localGUI); // TODO remove from server in _clear()
+    OnelabServer::instance()->addClient(_localGmsh); // TODO remove from server in _clear()
 
 #ifndef WIN32
-    pthread_create(&_serverThread, NULL, OnelabDatabase_server, NULL);
+    pthread_create(&_serverThread, NULL, OnelabDatabase_server, &(((OnelabLocalClient *)_localGmsh)->getName()));
 #else
     _serverThread = CreateThread(NULL, 0, NULL, OnelabDatabase_server, 0, NULL);
 #endif
-    return _localClient;
+    return _localGUI;
   }
-  GmshNetworkClient *useAsNetworkClient(UInt32 address, UInt16 port){
+  GmshNetworkClient *useAsNetworkClient(UInt32 address, UInt16 port, std::string cli="GUI"){
     // use this as a network client (take server address/port)
-    _clear();
+    if(!_client) {
+      _clear();
 
-    _client = new GmshNetworkClient("GUI", address, port);
-    if(_client->connect()) {
+      _client = new GmshNetworkClient(cli, address, port);
+      if(_client->connect()) {
+#ifndef WIN32
+        pthread_create(&_listenThread, NULL, OnelabDatabase_listen, &(((OnelabLocalClient *)_client)->getName()));
+#else
+        _listenThread = CreateThread(NULL, 0, NULL, OnelabDatabase_listen, 0, NULL);
+#endif
+        return _client;
+      }
+      else {
+        Msg::Error("Unable to connect to the server!");
+        return NULL;
+      }
+    }
+    else {
 #ifndef WIN32
-      pthread_create(&_listenThread, NULL, OnelabDatabase_listen, NULL);
+      pthread_create(&_listenThread, NULL, OnelabDatabase_listen, &(((OnelabLocalClient *)_client)->getName()));
 #else
       _listenThread = CreateThread(NULL, 0, NULL, OnelabDatabase_listen, 0, NULL);
 #endif
       return _client;
     }
-    else
-      Msg::Error("Unable to connect to the server!");
     return NULL;
   }
+  void networkClientHaveToStop(bool haveToStop) {_haveToStop = haveToStop;}
+  bool networkClientHaveToStop() {return _haveToStop;}
+  void haveToDo(const std::string action) {_action = action;}
+  std::string &actionToDo() {return _action;}
+  int wait() {
+    if(_client) return pthread_join(_listenThread, NULL);
+    return pthread_join(_serverThread, NULL);
+  }
   int listen(UInt8 *buff, unsigned int maxlen){
     if(_client) return _client->recvfrom(buff, maxlen);
     return 0;
@@ -95,25 +125,28 @@ public:
     _clear();
 
     OnelabServer::instance(address, port);
-    _localClient = new GmshLocalClient("localGUI", OnelabServer::instance()->getParameterSpace());
+    _localGUI = new GmshLocalClient("localGUI", OnelabServer::instance()->getParameterSpace());
 #ifndef WIN32
     pthread_create(&_serverThread, NULL, OnelabDatabase_server, NULL);
 #else
     _serverThread = CreateThread(NULL, 0, NULL, OnelabDatabase_server, 0, NULL);
 #endif
-    return _localClient;
-  }
-  template <class T> bool set(const T &p, bool update=true) {
-    if(_client) return _client->set(p, update);
-    //if(_localClient) return _localClient->set(p);
-    return OnelabServer::instance()->set(p, "");
+    return _localGUI;
   }
   template <class T> bool set(const T &p, const std::string &client) {
+    std::cout<<"set "<<p.getName()<<" from "<<client<<std::endl;
+    if(_client) return _client->set(p, true);
     return OnelabServer::instance()->set(p, client);
   }
+  template <class T> bool set(const T &p, bool update=true) {
+    std::cout<<"set "<<p.getName()<<std::endl;
+    if(_client) return _client->set(p, update);
+    //if(_localGUI) return _localGUI->set(p);
+    return OnelabServer::instance()->set(p);
+  }
   template <class T> bool get(std::vector<T> &ps, const std::string &name="", const std::string &client="") {
     if(_client) return _client->get(ps, name);
-    //if(_localClient) _localClient->get(ps, name);
+    //if(_localGUI) _localGUI->get(ps, name);
     return OnelabServer::instance()->get(ps, name, client);
   }
   bool fromFile(FILE *fp, const std::string &client="")
@@ -122,116 +155,62 @@ public:
     return OnelabServer::instance()->fromFile(fp, client);
 
   }
-  void onelab_cb(std::string action) {
-    if(_client) return; // TODO send action to the server
-    if(action == "stop"){
-      //FlGui::instance()->onelab->stop(true);
-      if(_client) _client->stop();
+  bool run(const std::string action, const std::string client="") {
+    UInt8 buff[1024];
+    OnelabProtocol msg(OnelabProtocol::OnelabAction);
+    if(client.size()) {
+      std::cout << "try to " << action << ' ' << client <<  std::endl;
+      onelab::string o(client + "/Action", action);
+      o.setVisible(false);
+      o.setNeverChanged(true);
+      set(o);
+      if(_client && ((OnelabLocalClient *)_client)->getName() == client) {
+        if(client == "Gmsh") onelabUtils::runGmshClient(action, true);
+      }
+      else if(_client) {
+        std::cout << "client is remote" << std::endl;
+        msg.attrs.push_back(new OnelabAttrAction(action, client));
+        int size = msg.encodeMsg(buff, 1024);
+        sendbytes(buff, size);
+        return true;
+      }
+      else {
+        std::cout << "client is local" << std::endl;
+        OnelabServer::instance()->performAction(action, client);
+        return true;
+      }
     }
-    //TODO if(action == "compute") initializeLoops();
+    else {
+      // run Gmsh client
+      run(action, "Gmsh");
 
-    do {
-      for (std::vector<OnelabLocalNetworkClient>::iterator it = OnelabServer::instance()->getClients().begin() ; it != OnelabServer::instance()->getClients().end(); ++it)
-      {
-        onelab::string o((*it).getName() + "/Action", action);
-        o.setVisible(false);
-        o.setNeverChanged(true);
-        this->set(o);
-        (*it).run();
+      // iterate over all other clients
+      if(_client) {
+        std::cout << "server is remote" << std::endl;
+        msg.attrs.push_back(new OnelabAttrAction(action, client));
+        int size = msg.encodeMsg(buff, 1024);
+        sendbytes(buff, size);
+        return true;
       }
-
-    } while(action == "compute" &&
-        //TODO incrementLoops() &&
-        !false/*TODO onelab->stop*/);
-
+      else {
+        std::cout << "server is local" << std::endl;
+        OnelabServer::instance()->performAction(action);
+        return true;
+      }
+    }
+    return false;
+  }
+  bool getChanged(const std::string &client="") const {
+    if(!_client)
+      return OnelabServer::instance()->getChanged(client);
+    else
+      return true; // TODO
+  }
+  void setChanged(bool changed, const std::string &client="") {
+    if(!_client)
+      OnelabServer::instance()->setChanged(changed, client);
+    else
+      return; // TODO
   }
 };
 
-#ifndef WIN32
-void *OnelabDatabase_listen(void *arg)
-#else
-DWORD WINAPI OnelabDatabase_listen(LPVOID arg)
-#endif
-{
-  OnelabProtocol msg(-1);
-  UInt8 buff[1024];
-  int recvlen = 0;
-  while(1) {
-    recvlen = OnelabDatabase::instance()->listen(buff, 1024);
-    if(recvlen == 1 && buff[0] == 'S')
-      break;
-    msg.parseMsg(buff, recvlen);
-    msg.showMsg();
-    switch(msg.msgType()) {
-      case OnelabProtocol::OnelabStop:
-        return NULL;
-      case OnelabProtocol::OnelabMessage:
-        Msg::Info("Message from onelab"); // TODO
-        break;
-      case OnelabProtocol::OnelabResponse:
-      case OnelabProtocol::OnelabUpdate:
-        for(std::vector<OnelabAttr *>::iterator it = msg.attrs.begin() ; it != msg.attrs.end(); ++it) {
-          if((*it)->getAttributeType() == OnelabAttr::Number) {
-            onelab::number *attr = (onelab::number *)*it;
-            OnelabDatabase::instance()->set(*attr, false);
-          }
-          else if((*it)->getAttributeType() == OnelabAttr::String) {
-            onelab::string *attr = (onelab::string *)*it;
-            OnelabDatabase::instance()->set(*attr, false);
-          }
-          else if((*it)->getAttributeType() == OnelabAttr::Region) {
-            onelab::region *attr = (onelab::region *)*it;
-            OnelabDatabase::instance()->set(*attr, false);
-          }
-          else if((*it)->getAttributeType() == OnelabAttr::Function) {
-            onelab::function *attr = (onelab::function *)*it;
-            OnelabDatabase::instance()->set(*attr, false);
-          }
-          else if((*it)->getAttributeType() == OnelabAttrFileQuery::attributeType()) {
-            OnelabAttrFileQuery *attr = (OnelabAttrFileQuery *)*it;
-            const char *filename = attr->getFilename();
-            // FIXME path/filename ?
-            std::clog << "try to open " << filename << " for reading" << std::endl;
-            FILE *fp = fopen(filename, "rb");
-            if(fp != NULL){
-              OnelabProtocol rep(OnelabProtocol::OnelabUpdate);
-              rep.attrs.push_back(new OnelabAttrFile(std::string(filename), fp));
-              recvlen = rep.encodeMsg(buff, 1024);
-              OnelabDatabase::instance()->sendbytes(buff, recvlen);
-              while((recvlen = fread(buff, 1, 1024, fp)) > 0)
-                OnelabDatabase::instance()->sendbytes(buff, recvlen);
-            }
-          }
-          else if((*it)->getAttributeType() == OnelabAttrFile::attributeType()) {
-            OnelabAttrFile *attr = (OnelabAttrFile *)*it;
-            const char *filename = attr->getFilename();
-            std::clog << "try to open " << filename << " for writing" << std::endl;
-            FILE *fp = fopen(filename, "wb");
-            if(fp != NULL){
-              unsigned int filesize = ((OnelabAttrFile *)attr)->getFileSize();
-              unsigned int downloadsize = 0;
-              while(downloadsize < filesize) {
-                recvlen = OnelabDatabase::instance()->listen(buff, 1024);
-                downloadsize += recvlen;
-                fwrite(buff, 1, recvlen, fp);
-              }
-            }
-          }
-          else if((*it)->getAttributeType() == OnelabAttrAction::attributeType()) {
-            OnelabAttrAction *attr = (OnelabAttrAction *)*it;
-            OnelabLocalNetworkClient *target = OnelabServer::instance()->getClient(attr->getClient());
-            target->sendto(buff, recvlen);
-          }
-        }
-        break;
-    }
-  }
-}
-#ifndef WIN32
-void *OnelabDatabase_server(void *arg)
-#else
-DWORD WINAPI OnelabDatabase_server(LPVOID arg)
-#endif
-{
-  OnelabServer::instance()->Run();
-}
diff --git a/contrib/onelab2/OnelabLocalClient.h b/contrib/onelab2/OnelabLocalClient.h
index 5d0303ec5e1cc9d3545493ec86f55afee05dd6c1..fd82ccab9c45bca90766d2aa92142b9f496566c7 100644
--- a/contrib/onelab2/OnelabLocalClient.h
+++ b/contrib/onelab2/OnelabLocalClient.h
@@ -15,18 +15,18 @@ public:
 	OnelabLocalClient(std::string name, onelab::parameterSpace *parameterSpace)
 		: VirtualClient(name, parameterSpace){
 	}
-	template <class T> bool set(const T &p){
-		return _parameterSpace->set(p, this->_name);
-	}
-	template <class T> bool get(std::vector<T> &ps, const std::string &name=""){
-		return _parameterSpace->get(ps, name, this->_name);
-	}
 	virtual ~OnelabLocalClient(){}
-	void onNewParameter(onelab::parameter *p){}
-  void onUpdateParameter(onelab::parameter *p){}
-  void onRemoveParameter(onelab::parameter *p){}
+  template <class T> bool set(const T &p){
+    return _parameterSpace->set(p, this->_name);
+  }
+  template <class T> bool get(std::vector<T> &ps, const std::string &name){
+  	return _parameterSpace->get(ps, name, _name);
+  }
+	virtual void onNewParameter(onelab::parameter *p){}
+  virtual void onUpdateParameter(onelab::parameter *p){}
+  virtual void onRemoveParameter(onelab::parameter *p){}
 
-  void run() {}
+  virtual void run(std::string action) {}
   void stop() {}
 };
 
diff --git a/contrib/onelab2/OnelabLocalNetworkClient.cpp b/contrib/onelab2/OnelabLocalNetworkClient.cpp
index 94060708b6503c04e57877a7a24681f64df2d650..69cdd39d76e2295f3b93ff4d44b5bdc9b34b0c34 100644
--- a/contrib/onelab2/OnelabLocalNetworkClient.cpp
+++ b/contrib/onelab2/OnelabLocalNetworkClient.cpp
@@ -48,9 +48,11 @@ int OnelabLocalNetworkClient::recvmsg(OnelabProtocol &msg)
   if(recvlen != 4) return recvlen;
   int msglen = msg.parseHeader(header, recvlen);
   // then recv the message
+  if(msglen == 0) return 4;
   buff = (UInt8 *) malloc(sizeof(UInt8)*msglen);
   recvlen = recvfrom(buff, msglen); // recvlen should be equals to msglen
   msg.parseMessage(buff, recvlen);
+  free(buff);
   return recvlen + 4;
 }
 void OnelabLocalNetworkClient::updateParameter(onelab::parameter *p)
@@ -61,3 +63,11 @@ void OnelabLocalNetworkClient::updateParameter(onelab::parameter *p)
   unsigned int recvlen = msg.encodeMsg(buff, 1024);
   sendto(buff, recvlen);
 }
+void OnelabLocalNetworkClient::run(std::string action)
+{
+  OnelabProtocol msg(OnelabProtocol::OnelabAction);
+  msg.attrs.push_back(new OnelabAttrAction(action, _name));
+  UInt8 buff[1024];
+  unsigned int size = msg.encodeMsg(buff, 1024);
+  sendto(buff, size);
+}
diff --git a/contrib/onelab2/OnelabLocalNetworkClient.h b/contrib/onelab2/OnelabLocalNetworkClient.h
index ca21c6696019df168f1f9064d49e04b22380a8ee..17f94a471c7cebe5bc2bd6ff5fc93e253e804f23 100644
--- a/contrib/onelab2/OnelabLocalNetworkClient.h
+++ b/contrib/onelab2/OnelabLocalNetworkClient.h
@@ -35,7 +35,7 @@ public:
 	unsigned int getIp() {return _ip.address;}
 	unsigned short getPort() {return _ip.port;}
 
-  void run() {}
-  void stop() {}
+  void run(std::string action);
+  void stop() {} // TODO
 };
 #endif
diff --git a/contrib/onelab2/OnelabNetworkClient.cpp b/contrib/onelab2/OnelabNetworkClient.cpp
index 6db37ee4c459b02ea3e3a5066d3b989999154ce4..5d1fcc5b0f0ee3bc51686332d3a61aa7002119ec 100644
--- a/contrib/onelab2/OnelabNetworkClient.cpp
+++ b/contrib/onelab2/OnelabNetworkClient.cpp
@@ -80,12 +80,22 @@ int OnelabNetworkClient::recvfrom(UInt8 *buff, UInt16 maxlen)
   return udt_socket_recv(_fdu, buff, maxlen);
 #endif
 }
-void OnelabNetworkClient::recvfrom(OnelabProtocol &msg)
+int OnelabNetworkClient::recvfrom(OnelabProtocol &msg)
 {
-  UInt16 bufflen = 1024, recvlen = 0;
-  UInt8 buff[1024];
-  recvlen = this->recvfrom(buff, bufflen);
-  msg.parseMsg(buff, recvlen);
+  UInt8 header[8];
+  UInt8 *buff = NULL;
+  int recvlen = 0;
+  // recv the header
+  recvlen = recvfrom(header, 4);
+  if(recvlen != 4) return recvlen;
+  int msglen = msg.parseHeader(header, recvlen);
+  // then recv the message
+  if(msglen == 0) return 4;
+  buff = (UInt8 *) malloc(sizeof(UInt8)*msglen);
+  recvlen = recvfrom(buff, msglen); // recvlen should be equals to msglen
+  msg.parseMessage(buff, recvlen);
+  free(buff);
+  return recvlen + 4;
 }
 bool OnelabNetworkClient::connect()
 {
@@ -110,7 +120,7 @@ bool OnelabNetworkClient::connect()
 #ifdef HAVE_UDT
   udt_socket_timeout(_fdu, 3);
 #endif
-  //ip4_socket_timeout(_fds, 3);
+  ip4_socket_timeout(_fds, 3);
   recvlen = recvfrom(buff, bufflen);
 
 #ifdef HAVE_UDT
diff --git a/contrib/onelab2/OnelabNetworkClient.h b/contrib/onelab2/OnelabNetworkClient.h
index b4f602217e0af043718eda38f347e4ad7097cdcc..b627b40f50f8c0f16a2ff73684f1f31c50c0fb3a 100644
--- a/contrib/onelab2/OnelabNetworkClient.h
+++ b/contrib/onelab2/OnelabNetworkClient.h
@@ -2,11 +2,15 @@
 #define _ONELABCLIENT_H_
 
 #include <vector>
+#include <unistd.h>
 
-#include "NetworkUtils.h"
 #include "VirtualClient.h"
-#include "OnelabLocalNetworkClient.h"
 #include "OnelabProtocol.h"
+#ifdef HAVE_UDT
+#include "UdtUtils.h"
+#else
+#include "NetworkUtils.h"
+#endif
 
 class OnelabNetworkClient : VirtualClient
 {
@@ -23,7 +27,16 @@ private:
 		OnelabProtocol msg(OnelabProtocol::OnelabRequest);
 		msg.attrs.push_back(new OnelabAttrParameterQuery(name.c_str(), T::attributeType()));
 		this->request(msg);
-		return true;
+		// wait for the answer
+    fd_set readfds;
+    struct timeval timeout;
+    timeout.tv_sec = 1;
+    timeout.tv_usec = 0;
+    FD_ZERO(&readfds);
+    FD_SET(_fds, &readfds);
+    int nfds = select(_fds+1, &readfds, NULL, NULL, &timeout);
+    usleep(100000); // FIXME sleep while read the buffer
+    return nfds > 0;
 	}
 	void requestParameters(); // request all parameter for this client
 public:
@@ -59,7 +72,10 @@ public:
 	}
 	template <class T> bool get(std::vector<T> &ps, const std::string &name=""){
 		if(_parameterSpace->get(ps, name, this->_name) && ps.size() == 0)
-			return requestParameter(ps, name);
+			if(requestParameter(ps, name))
+        return _parameterSpace->get(ps, name, this->_name) && ps.size() == 0;
+      else
+        return false;
 		return true;
 	}
   FILE *openFile(const std::string name, const char *mode="rb")
@@ -121,15 +137,14 @@ public:
 	// network specific method
 	bool connect();
 	bool isConnected(){return _connected;}
-	void recvfrom(OnelabProtocol &msg);
+	int recvfrom(OnelabProtocol &msg);
 	int recvfrom(UInt8 *buff, UInt16 maxlen);
 	void sendto(UInt8 *buff, UInt16 len);
 	void disconnect();
 	void setRemoteIP(unsigned long ip){if(!_connected) _ip.address=ip;}
 	void setRemotePort(unsigned short port){if(!_connected) _ip.port=port;}
 
-  void run() {}
-  void stop() {}
+  void run(std::string action) {}
 };
 
 #endif
diff --git a/contrib/onelab2/OnelabProtocol.cpp b/contrib/onelab2/OnelabProtocol.cpp
index 416d1d1af9bae347bdc6e565d4825269db24979f..dd03b8e6b9580fce051e0bfc312cbb3db678de18 100644
--- a/contrib/onelab2/OnelabProtocol.cpp
+++ b/contrib/onelab2/OnelabProtocol.cpp
@@ -57,7 +57,7 @@ UInt32 OnelabProtocol::parseMessage(UInt8 *buff, UInt32 len)
 {
   UInt8 *ptr = buff;
   UInt8 *payload = ptr;
-  unsigned short parsed = 4;
+  unsigned short parsed = 4; // header size
   unsigned short size = _size;
 	while(size >= 4) {
 		UInt16 attrType = 0;
@@ -96,6 +96,10 @@ UInt32 OnelabProtocol::parseMessage(UInt8 *buff, UInt32 len)
 				this->attrs.push_back(new OnelabAttrParameterQuery());
 				((OnelabAttrParameterQuery *)this->attrs.back())->parseAttribute(ptr, attrSize);
 				break;
+      case 0x10:
+        this->attrs.push_back(new OnelabAttrAction());
+				((OnelabAttrAction *)this->attrs.back())->parseAttribute(ptr, attrSize);
+				break;
       case 0x0b:
 				this->attrs.push_back(new OnelabAttrFileQuery());
 				((OnelabAttrFileQuery *)this->attrs.back())->parseAttribute(ptr, attrSize);
@@ -113,7 +117,7 @@ UInt32 OnelabProtocol::parseMessage(UInt8 *buff, UInt32 len)
 		}
 		ptr += attrSize;
 		size -= attrSize;
-    parsed += attrSize+4;
+    parsed += (attrSize+4);
 	}
   if(parsed != len) {std::cout << "parse - size left:"  << len-parsed << '-' << size << "(len is "<< len <<" and parsed is "<< parsed <<" )" << std::endl;}
  
@@ -172,6 +176,10 @@ UInt32 OnelabProtocol::parseMsg(UInt8 *buff, UInt32 len)
 				this->attrs.push_back(new OnelabAttrParameterQuery());
 				((OnelabAttrParameterQuery *)this->attrs.back())->parseAttribute(ptr, attrSize);
 				break;
+      case 0x10:
+        this->attrs.push_back(new OnelabAttrAction());
+				((OnelabAttrAction *)this->attrs.back())->parseAttribute(ptr, attrSize);
+				break;
       case 0x0b:
 				this->attrs.push_back(new OnelabAttrFileQuery());
 				((OnelabAttrFileQuery *)this->attrs.back())->parseAttribute(ptr, attrSize);
diff --git a/contrib/onelab2/OnelabProtocol.h b/contrib/onelab2/OnelabProtocol.h
index 2179bfbe5ca1524c938a9b21380533a5c9d01f8f..1380da79b6df1ac8e4011de3c4842ab4aefcc78d 100644
--- a/contrib/onelab2/OnelabProtocol.h
+++ b/contrib/onelab2/OnelabProtocol.h
@@ -32,11 +32,12 @@ public:
 	static const UInt8 BindResponseMsg	= 0x02;
 	static const UInt8 BindMessageMsg	= 0x03;
 
-	static const UInt8 OnelabStart		= 0x10;
-	static const UInt8 OnelabStop		= 0x11;
+	static const UInt8 OnelabStart		= 0x10; // Client send his name to the server (first message)
+	static const UInt8 OnelabStop 		= 0x11; // Client say to the server he is going to stop / the server ask a client to stop
 	static const UInt8 OnelabMessage	= 0x12;
 	static const UInt8 OnelabRequest	= 0x13;
 	static const UInt8 OnelabResponse	= 0x14;
 	static const UInt8 OnelabUpdate		= 0x15;
+	static const UInt8 OnelabAction		= 0x16;
 };
 #endif
diff --git a/contrib/onelab2/OnelabServer.cpp b/contrib/onelab2/OnelabServer.cpp
index 1c757b26da8696f387249dbec7a5ef845f56ddf0..2959173e024c6cfcea1d95836082af7d52de6b85 100644
--- a/contrib/onelab2/OnelabServer.cpp
+++ b/contrib/onelab2/OnelabServer.cpp
@@ -7,11 +7,19 @@
 #include <wspiapi.h>
 #endif
 
+#include "NetworkUtils.h"
 #include "OnelabServer.h"
 #include "OnelabProtocol.h"
 #include "OnelabAttributes.h"
 #include "onelab.h"
-#include "NetworkUtils.h"
+#include "onelabUtils.h"
+
+// FIXME no Gmsh specific header (used in launchClient)
+#include "StringUtils.h"
+#include "GmshMessage.h"
+#include "OS.h"
+#include "GModel.h"
+#include "Options.h"
 
 static bool haveToStop = false;
 
@@ -62,6 +70,56 @@ OnelabLocalNetworkClient *OnelabServer::getClient(UDTSOCKET fd) // UDTSOCKET Soc
 }
 #endif
 
+int OnelabServer::launchClient(const std::string &client) // FIXME OnelabDatabase instead of OnelabServer ?
+{
+  // launch a new client with a system call
+  std::string command = "";
+  if(getClient(client) != NULL || getLocalClient(client) != NULL) return -1; // client already exist
+
+  if(client == "Gmsh") {
+    command.assign(Msg::GetExecutableName());
+  }
+  else {
+    int num = 0;
+    while(num < 10/*NUM_SOLVERS*/){
+      if(opt_solver_name(num, GMSH_GET, "") == client) break;
+      num++;
+    }
+    if(num >= 10/*NUM_SOLVERS*/) {
+      std::cout << "Unable to find " << client << std::endl;
+      return -1;
+    }
+
+    //std::string name = opt_solver_name(num, GMSH_GET, "");
+    std::string exe = opt_solver_executable(num, GMSH_GET, "");
+    command.assign(exe);
+  }
+  //std::string command = FixWindowsPath(_client->getExecutable()); // TODO
+
+  if(command.size()){
+    std::vector<std::string> args = onelabUtils::getCommandLine(client);
+    for(unsigned int i = 0; i < args.size(); i++)
+      command.append(" " + args[i]);
+  }
+  command.append(" -onelab"
+                 " \"" + client + "\" %s");
+
+  char cmd[1024];
+  // UNIX socket
+  //TODO sprintf(cmd, command, _sockname.c_str());
+
+  // TCP socket
+  if(client == "Gmsh") sprintf(cmd, command.c_str(), "-server %s:%d");
+  else sprintf(cmd, command.c_str(), " %s:%d");
+  command.assign(cmd);
+  sprintf(cmd, command.c_str(), (_ip.address==0)?"127.0.0.1":ip4_inet_ntop(_ip.address).c_str(), _ip.port);
+
+  std::cout << "launch " << client << " with command: " << cmd << std::endl;
+  SystemCall(cmd);
+
+  return 0;
+}
+
 //void OnelabServer::addClient(std::string name, Socket fd, UInt32 ip, UInt16 port)
 //{
 //  if(ip == 0 || port == 0) throw "Unable to add client (invalid ip or port)";
@@ -100,6 +158,15 @@ OnelabLocalNetworkClient *OnelabServer::getClient(std::string name)
   }
   return NULL;
 }
+OnelabLocalClient *OnelabServer::getLocalClient(std::string name)
+{
+  for(std::vector<OnelabLocalClient *>::iterator it = _localClients.begin(); it != _localClients.end(); ++it) {
+    if((*it)->getName() == name)
+      return (*it);
+  }
+  return NULL;
+
+}
 
 void OnelabServer::removeClient(OnelabLocalNetworkClient *client)
 {
@@ -111,6 +178,57 @@ void OnelabServer::removeClient(OnelabLocalNetworkClient *client)
   }
 }
 
+void OnelabServer::performAction(const std::string action, const std::string client)
+{
+  if(client.size()) {
+    OnelabLocalNetworkClient *cli = getClient(client);
+    OnelabLocalClient *localcli = getLocalClient(client);
+    if(cli != NULL || localcli == NULL) {
+      onelab::string o(client + "/Action", action);
+      o.setVisible(false);
+      o.setNeverChanged(true);
+      set(o);
+    }
+    if(cli != NULL){ // Gmsh is used as a server and the client is remote
+      std::cout << action << " on " << client << "(client is remote)" << std::endl;
+      cli->run(action);
+    }
+    else if(localcli != NULL){ // client is local (in the same memory space than this server)
+      std::cout << action << " on " << client << "(client is local)" << std::endl;
+      localcli->run(action);
+    }
+    else { // client is Gmsh but do not exist (Gmsh is used as a server), launch Gmsh
+      std::cout << action << " on " << client << "(launch a new remote Gmsh)" << std::endl;
+      if(launchClient(client) >= 0)
+        ;// FIXME then action or action is store in onelab DB ?
+      else
+        ;// TODO save action and wait for the cli ?
+    }
+  }
+  else {
+    // run all non Gmsh clients TODO, exclude GUI ?
+    for(std::vector<OnelabLocalNetworkClient>::iterator it = _clients.begin(); it != _clients.end(); ++it) {
+      if((*it).getName() == "Gmsh") continue;
+      std::cout << action << " on " << (*it).getName() << "(remote)" << std::endl;
+      onelab::string o((*it).getName() + "/Action", action);
+      o.setVisible(false);
+      o.setNeverChanged(true);
+      set(o);
+      (*it).run(action);
+    }
+
+    for(std::vector<OnelabLocalClient *>::iterator it = _localClients.begin(); it != _localClients.end(); ++it) {
+      if((*it)->getName() == "Gmsh") continue;
+      onelab::string o((*it)->getName() + "/Action", action);
+      o.setVisible(false);
+      o.setNeverChanged(true);
+      set(o);
+      std::cout << action << " on " << (*it)->getName() << "(local)" << std::endl;
+      (*it)->run(action);
+    }
+  }
+}
+
 #ifdef HAVE_UDT
 #ifndef WIN32
 void *listenOnClients(void *param)
@@ -122,22 +240,40 @@ void *listenOnClients(void *param)
   std::set<UDTSOCKET> fdus;
   std::set<Socket> fdss;
   int recvlen = 0;
-  UInt8 prev[1024];
   UInt8 buff[1024];
   OnelabProtocol msg(-1), rep(-1);
   int eid = OnelabServer::instance()->getEID();
   while(UDT::ERROR != UDT::epoll_wait(eid, &fdus, NULL, -1, &fdss, NULL)) {
-    //for(std::set<UDTSOCKET>::iterator it = fdus.begin(); it != fdus.end(); ++it) {
+    /*for(std::set<UDTSOCKET>::iterator it = fdus.begin(); it != fdus.end(); ++it) {
+      OnelabLocalNetworkClient *cli = OnelabServer::instance()->getClient(*it);
+      if(cli == NULL) { // Client is not in the list (it muste be a Start message)
+        IPv4 ip;
+        recvlen = udt_socket_recv(*it, buff, 1024);
+    }TODO*/
 
     for(std::set<Socket>::iterator it = fdss.begin(); it != fdss.end(); ++it) {
 
       OnelabLocalNetworkClient *cli = OnelabServer::instance()->getClient(*it);
-      if(cli == NULL) {
+      if(cli == NULL) { // Client is not in the list (it muste be a Start message)
         IPv4 ip;
-        //recvlen = udt_socket_recv(*it, buff, 1024);
-        recvlen = ip4_socket_recv(*it, buff, 1024, ip); // FIXME
-        std::clog << "recv " << recvlen << std::endl;
-        msg.parseMsg(buff, recvlen);
+        // recv the header
+        recvlen = ip4_socket_recv(*it, buff, 4, ip);
+        if(recvlen != 4) {
+          // invalid message header
+          UDT::epoll_remove_ssock(eid, *it);
+          UDT::close(*it);
+          continue;
+        }
+        int msglen = msg.parseHeader(buff, recvlen);
+        if(msglen > 1024) {
+          // FIXME? buffer is too small
+          UDT::epoll_remove_ssock(eid, *it);
+          UDT::close(*it);
+          continue;
+        }
+        // then recv the message
+        recvlen = ip4_socket_recv(*it, buff, msglen, ip);
+        msg.parseMessage(buff, recvlen);
         msg.showMsg();
         if(msg.msgType() == OnelabProtocol::OnelabStart && msg.attrs.size() > 0 && msg.attrs[0]->getAttributeType() == OnelabAttr::Start) {
           std::string name = std::string(((OnelabAttrStart *)msg.attrs[0])->name());
@@ -153,6 +289,7 @@ void *listenOnClients(void *param)
             UDT::close(*it);
             continue;
           }
+          // Add a new remote client
           OnelabServer::instance()->addClient(name, *it, ip.address, ip.port);
           std::clog << "\033[0;31m" << "Add a new client: " << name <<  "\033[0m" << std::endl;
           OnelabProtocol rep(OnelabProtocol::OnelabStart);
@@ -171,7 +308,6 @@ void *listenOnClients(void *param)
         }
       }
       else {
-        std::cout << "ok" << std::endl;
         try {
           recvlen = cli->recvmsg(msg);
         }
@@ -189,6 +325,7 @@ void *listenOnClients(void *param)
             OnelabServer::instance()->removeClient(cli);
             UDT::close(*it);
             }*/
+          std::cerr << "Error while recv message." << std::endl;
           continue;
         }
         if(recvlen == 0) { // for TCP
@@ -199,7 +336,6 @@ void *listenOnClients(void *param)
           continue;
         }
         std::clog << "recv " << recvlen << " bytes on client " << cli->getName() << std::endl;
-        //unreaded = msg.parseMsg(buff, recvlen);
         switch (msg.msgType()) {
         case OnelabProtocol::OnelabStop:
           std::cout << "\033[0;31m" << "Client \"" << cli->getName() << "\" is going to stop" << "\033[0m" << std::endl; // DEBUG
@@ -212,6 +348,7 @@ void *listenOnClients(void *param)
           UDT::close(*it);
           break;
         case OnelabProtocol::OnelabMessage:
+          std::cout << "recv a message ... (TODO)" << std::endl;
           // TODO
           break;
         case OnelabProtocol::OnelabRequest:
@@ -319,6 +456,25 @@ void *listenOnClients(void *param)
               }
           }
           break;
+          case OnelabProtocol::OnelabAction:
+          {
+            if(msg.attrs.size()==1 && msg.attrs[0]->getAttributeType() == OnelabAttrAction::attributeType()) {
+              std::clog << "\033[0;31m" << "Client " << cli->getName() << " ask " << ((OnelabAttrAction *)msg.attrs[0])->getClient() << " to " << ((OnelabAttrAction *)msg.attrs[0])->getAction() <<  "\033[0m" << std::endl;
+              OnelabServer::instance()->performAction(((OnelabAttrAction *)msg.attrs[0])->getAction(), ((OnelabAttrAction *)msg.attrs[0])->getClient());
+              //OnelabLocalNetworkClient *cli = OnelabServer::instance()->getClient(((OnelabAttrAction *)msg.attrs[0])->getClient());
+              //OnelabLocalClient *localcli = OnelabServer::instance()->getLocalClient(((OnelabAttrAction *)msg.attrs[0])->getClient());
+              //std::cout << ((OnelabAttrAction *)msg.attrs[0])->getAction() << " on " << ((OnelabAttrAction *)msg.attrs[0])->getClient() << "(" << cli <<  " or local " << localcli << ")" << std::endl;
+              //if(cli == NULL && localcli == NULL) {
+              //}
+              //if(cli != NULL)
+              //  cli->run(((OnelabAttrAction *)msg.attrs[0])->getAction());
+              //else if(localcli != NULL)
+              //  localcli->run(((OnelabAttrAction *)msg.attrs[0])->getAction());
+              //else
+              //  ;// TODO save action and wait for the cli ?
+            }
+          }
+          break;
         }
       }
     }
@@ -372,12 +528,6 @@ void OnelabServer::Run()
       pthread_create(&listen_thread, NULL, listenOnClients, NULL);
 #else
       listen_thread = CreateThread(NULL, 0, listenOnClients, NULL, 0, NULL);
-#endif
-    if(_clients.size() == 1)
-#ifndef WIN32
-      pthread_join(listen_thread, NULL);
-#else
-      WaitForSingleObject(listen_thread, INFINITE);
 #endif
   }
   udt_socket_close(_fdu);
diff --git a/contrib/onelab2/OnelabServer.h b/contrib/onelab2/OnelabServer.h
index 81b773b9445b3b5749a0bfb7a26a15e72038cb50..1db3bbae54c3f61a887827163319f50c24e4fd4b 100644
--- a/contrib/onelab2/OnelabServer.h
+++ b/contrib/onelab2/OnelabServer.h
@@ -39,6 +39,7 @@ public:
 	}
 	static void setInstance(OnelabServer *s) { _server = s; }
   onelab::parameterSpace *getParameterSpace() {return &_parameterSpace;}
+  UInt16 getPort() { return _ip.port;}
 #ifdef HAVE_UDT
 	~OnelabServer(){UDT::cleanup();}
 #else
@@ -54,11 +55,13 @@ public:
 	void addClient(std::string name, UInt32 ip, UInt16 port);
 #endif
   void addClient(OnelabLocalClient *cli) {_localClients.push_back(cli);}
+  int launchClient(const std::string &);
 	void removeClient(OnelabLocalNetworkClient *client);
   std::vector<OnelabLocalNetworkClient> &getClients() {return _clients;}
   std::vector<OnelabLocalClient *> &getLocalClients() {return _localClients;}
 	OnelabLocalNetworkClient *getClient(UInt32 ip, UInt16 port);
 	OnelabLocalNetworkClient *getClient(std::string name);
+  OnelabLocalClient *getLocalClient(std::string name);
 	void sendAllParameter(OnelabLocalNetworkClient *cli);
 	// Parameters methods
 	void clear(const std::string &name="", const std::string &client="") {
@@ -74,10 +77,14 @@ public:
 		_parameterSpace.set(p, client);
     T *pp;
     _parameterSpace.getPtr(&pp, p.getName());
-    for(std::vector<OnelabLocalClient *>::iterator it = _localClients.begin() ; it != _localClients.end(); ++it)
-      if((*it)->getName() != client)
+    if(pp->getVisible()) pp->addClient("GUI", true);
+    for(std::vector<OnelabLocalClient *>::iterator it = _localClients.begin() ; it != _localClients.end(); ++it) {
+      std::cout << (*it)->getName() << " and is " << ((isNew)?"new ":"updated ") << " from " << client << std::endl;
+      if((*it)->getName() != client) {
         if(isNew)(*it)->onNewParameter(pp);
         else (*it)->onUpdateParameter(pp);
+      }
+    }
     std::map<std::string, bool> clients = p.getClients();
     for(std::map<std::string, bool>::const_iterator it = clients.begin(); it != clients.end(); it++) {
       std::cout << "send " << p.getName() << " to " << it->first << " from " << client << std::endl; 
@@ -86,6 +93,7 @@ public:
       if(tmp == NULL) continue;
       tmp->updateParameter(pp);
     }
+    return true;
 	}
 	template <class T> bool get(std::vector<T> &ps, const std::string &name="", const std::string &client="") {
 		return _parameterSpace.get(ps, name, client);
@@ -122,5 +130,14 @@ public:
     if(onelab::parameter::fromFile(msg, fp)) return fromChar(msg, client);
     return false;
   }
+  bool getChanged(const std::string &client="") const {
+    return _parameterSpace.getChanged(client);
+  }
+  void setChanged(bool changed, const std::string &client="") {
+    _parameterSpace.setChanged(changed, client);
+    std::cout << "set " << client << ((changed)?" changed ":" unchanged ") << std::endl
+      << "get " << getChanged(client) << std::endl;
+  }
+  void performAction(const std::string action, const std::string client="");
 };
 #endif
diff --git a/contrib/onelab2/VirtualClient.h b/contrib/onelab2/VirtualClient.h
index 01c28bd48bd5a926b89e2db2bd7c5625b2401c83..a664d44d8a1c2b4e2aef018dd0bdc885df9ac409 100644
--- a/contrib/onelab2/VirtualClient.h
+++ b/contrib/onelab2/VirtualClient.h
@@ -38,8 +38,7 @@ public:
   virtual void onUpdateParameter(onelab::parameter *) = 0;
   virtual void onRemoveParameter(onelab::parameter *) = 0;
 
-  virtual void run() = 0;
-  virtual void stop() = 0;
+  virtual void run(std::string action) = 0;
 };
 
 #endif