From f8544dbc2334f5c5d0b7aac9e5348a91e6a6c598 Mon Sep 17 00:00:00 2001
From: Christophe Geuzaine <cgeuzaine@ulg.ac.be>
Date: Sun, 21 Oct 2012 11:08:25 +0000
Subject: [PATCH] better logic in runGmshClient + renamed autoSaveSolutions to
 autoSaveOutputFiles

---
 Common/Context.h           |  2 +-
 Common/DefaultOptions.h    |  4 ++--
 Common/OS.cpp              |  6 ++++--
 Common/Options.cpp         |  6 +++---
 Common/Options.h           |  2 +-
 Common/onelabUtils.cpp     | 40 ++++++++++++++++++++++----------------
 Fltk/onelabWindow.cpp      | 16 ++++++++-------
 Geo/GeoStringInterface.cpp | 10 ++++++++++
 doc/texinfo/gmsh.texi      |  5 ++++-
 utils/misc/gmsh_app.plist  |  9 +++++++++
 10 files changed, 66 insertions(+), 34 deletions(-)

diff --git a/Common/Context.h b/Common/Context.h
index 8b73991768..66efa9498c 100644
--- a/Common/Context.h
+++ b/Common/Context.h
@@ -222,7 +222,7 @@ class CTX {
     double timeout;
     std::string socketName;
     std::string name[5], executable[5], remoteLogin[5];
-    int autoSaveDatabase, autoArchiveSolutions, autoMesh, autoMergeFile;
+    int autoSaveDatabase, autoArchiveOutputFiles, autoMesh, autoMergeFile;
     int autoHideNewViews, autoShowLastStep;
   }solver;
   // print options
diff --git a/Common/DefaultOptions.h b/Common/DefaultOptions.h
index e8880776e4..71c5af3ed6 100644
--- a/Common/DefaultOptions.h
+++ b/Common/DefaultOptions.h
@@ -1106,8 +1106,8 @@ StringXNumber MeshOptions_Number[] = {
 StringXNumber SolverOptions_Number[] = {
   { F|O, "AlwaysListen" , opt_solver_listen , 0. ,
     "Always listen to incoming connection requests?" },
-  { F|O, "AutoArchiveSolutions" , opt_solver_auto_archive_solutions , 0. ,
-    "Automatically archive solutions after each computation" },
+  { F|O, "AutoArchiveOutputFiles" , opt_solver_auto_archive_output_files , 0. ,
+    "Automatically archive output files after each computation" },
   { F|O, "AutoSaveDatabase" , opt_solver_auto_save_database , 1. ,
     "Automatically save database after each computation" },
   { F|O, "AutoMesh" , opt_solver_auto_mesh , 1. ,
diff --git a/Common/OS.cpp b/Common/OS.cpp
index d696e6d4e6..049a54c920 100644
--- a/Common/OS.cpp
+++ b/Common/OS.cpp
@@ -155,11 +155,13 @@ int StatFile(const std::string &fileName)
 {
 #if !defined(WIN32) || defined(__CYGWIN__)
   struct stat buf;
-  return stat(fileName.c_str(), &buf);
+  int ret = stat(fileName.c_str(), &buf);
+  // could get file modification time from buf
 #else
   struct _stat buf;
-  return _stat(fileName.c_str(), &buf);
+  int ret _stat(fileName.c_str(), &buf);
 #endif
+  return ret;
 }
 
 int CreateDirectory(const std::string &dirName)
diff --git a/Common/Options.cpp b/Common/Options.cpp
index 62f86bf6c0..895d8c5c22 100644
--- a/Common/Options.cpp
+++ b/Common/Options.cpp
@@ -5732,11 +5732,11 @@ double opt_solver_auto_save_database(OPT_ARGS_NUM)
   return CTX::instance()->solver.autoSaveDatabase;
 }
 
-double opt_solver_auto_archive_solutions(OPT_ARGS_NUM)
+double opt_solver_auto_archive_output_files(OPT_ARGS_NUM)
 {
   if(action & GMSH_SET)
-    CTX::instance()->solver.autoArchiveSolutions = (int)val;
-  return CTX::instance()->solver.autoArchiveSolutions;
+    CTX::instance()->solver.autoArchiveOutputFiles = (int)val;
+  return CTX::instance()->solver.autoArchiveOutputFiles;
 }
 
 double opt_solver_auto_mesh(OPT_ARGS_NUM)
diff --git a/Common/Options.h b/Common/Options.h
index 6c6e2e7ef6..07372c2c6e 100644
--- a/Common/Options.h
+++ b/Common/Options.h
@@ -469,7 +469,7 @@ double opt_solver_listen(OPT_ARGS_NUM);
 double opt_solver_timeout(OPT_ARGS_NUM);
 double opt_solver_plugins(OPT_ARGS_NUM);
 double opt_solver_auto_save_database(OPT_ARGS_NUM);
-double opt_solver_auto_archive_solutions(OPT_ARGS_NUM);
+double opt_solver_auto_archive_output_files(OPT_ARGS_NUM);
 double opt_solver_auto_mesh(OPT_ARGS_NUM);
 double opt_solver_auto_merge_file(OPT_ARGS_NUM);
 double opt_solver_auto_hide_new_views(OPT_ARGS_NUM);
diff --git a/Common/onelabUtils.cpp b/Common/onelabUtils.cpp
index 8cb37dbccd..a5015016fd 100644
--- a/Common/onelabUtils.cpp
+++ b/Common/onelabUtils.cpp
@@ -53,13 +53,14 @@ namespace onelabUtils {
 
   std::string getMshFileName(onelab::client *c)
   {
+    std::string name;
     std::vector<onelab::string> ps;
     c->get(ps, "Gmsh/MshFileName");
     if(ps.size()){
-      return ps[0].getValue();
+      name = ps[0].getValue();
     }
     else{
-      std::string name = CTX::instance()->outputFileName;
+      name = CTX::instance()->outputFileName;
       if(name.empty()){
         if(CTX::instance()->mesh.fileFormat == FORMAT_AUTO)
           name = GetDefaultFileName(FORMAT_MSH);
@@ -69,8 +70,17 @@ namespace onelabUtils {
       onelab::string o("Gmsh/MshFileName", name, "Mesh name");
       o.setKind("file");
       c->set(o);
-      return name;
     }
+
+    // we could keep track of mesh file name in "Output files" so we could
+    // archive the mesh automatically:
+    /*
+      onelab::string copy("Gmsh/9Output files", name, "Mesh name");
+      copy.setKind("file");
+      copy.setVisible(false);
+      c->set(copy);
+    */
+    return name;
   }
 
   void guessModelName(onelab::client *c)
@@ -268,16 +278,8 @@ namespace onelabUtils {
     std::string mshFileName = onelabUtils::getMshFileName(c);
     if(action == "initialize") return redraw;
 
-    static std::string modelName = "";
-    // FIXME: need to check if mesh file date is newer than model file
-    // date... or at least find a better solution
-    if(modelName.empty()){
-      // first pass is special to prevent model reload, as well as
-      // remeshing if a mesh file already exists on disk
-      modelName = GModel::current()->getName();
-      if(!StatFile(mshFileName))
-        onelab::server::instance()->setChanged(false, "Gmsh");
-    }
+    static std::string modelName = GModel::current()->getName();
+    static bool firstComputation = true;
 
     if(action == "check"){
       if(onelab::server::instance()->getChanged("Gmsh") ||
@@ -292,13 +294,16 @@ namespace onelabUtils {
     else if(action == "compute"){
       if(onelab::server::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
+        // 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());
-        if(!GModel::current()->empty() && meshAuto){
+        if(firstComputation && !StatFile(mshFileName)){
+          Msg::Info("Skipping mesh generation: assuming '%s' is up-to-date",
+                    mshFileName.c_str());
+        }
+        else if(!GModel::current()->empty() && meshAuto){
           GModel::current()->mesh(3);
           CreateOutputFile(mshFileName, CTX::instance()->mesh.fileFormat);
         }
@@ -311,6 +316,7 @@ namespace onelabUtils {
           CreateOutputFile(mshFileName, CTX::instance()->mesh.fileFormat);
         }
       }
+      firstComputation = false;
       onelab::server::instance()->setChanged(false, "Gmsh");
     }
 
diff --git a/Fltk/onelabWindow.cpp b/Fltk/onelabWindow.cpp
index fe53a6d0dc..ffc3dcf4a2 100644
--- a/Fltk/onelabWindow.cpp
+++ b/Fltk/onelabWindow.cpp
@@ -405,7 +405,7 @@ static void saveDb(const std::string &fileName)
     Msg::Error("Could not save database '%s'", fileName.c_str());
 }
 
-static void archiveSolutions(const std::string &fileName)
+static void archiveOutputFiles(const std::string &fileName)
 {
   std::string stamp = timeStamp();
 
@@ -415,6 +415,7 @@ static void archiveSolutions(const std::string &fileName)
   for(unsigned int i = 0; i < strings.size(); i++){
     if(strings[i].getName().find("9Output files") != std::string::npos){
       std::vector<std::string> names = strings[i].getChoices();
+      names.push_back(strings[i].getValue());
       for(unsigned int j = 0; j < names.size(); j++){
         std::vector<std::string> split = SplitFileName(names[j]);
         int n = split[1].size();
@@ -428,8 +429,9 @@ static void archiveSolutions(const std::string &fileName)
           rename(old.c_str(), names[j].c_str());
         }
       }
-      strings[i].setChoices(names);
       strings[i].setValue(names.back());
+      names.pop_back();
+      strings[i].setChoices(names);
       onelab::server::instance()->set(strings[i]);
     }
   }
@@ -589,9 +591,9 @@ void onelab_cb(Fl_Widget *w, void *data)
           incrementLoops());
 
   if(action == "compute" && (CTX::instance()->solver.autoSaveDatabase ||
-                             CTX::instance()->solver.autoArchiveSolutions)){
+                             CTX::instance()->solver.autoArchiveOutputFiles)){
     std::string db = SplitFileName(GModel::current()->getFileName())[0] + "onelab.db";
-    if(CTX::instance()->solver.autoArchiveSolutions) archiveSolutions(db);
+    if(CTX::instance()->solver.autoArchiveOutputFiles) archiveOutputFiles(db);
     if(CTX::instance()->solver.autoSaveDatabase) saveDb(db);
   }
 
@@ -609,7 +611,7 @@ void onelab_option_cb(Fl_Widget *w, void *data)
   if(what == "save")
     CTX::instance()->solver.autoSaveDatabase = val;
   else if(what == "archive")
-    CTX::instance()->solver.autoArchiveSolutions = val;
+    CTX::instance()->solver.autoArchiveOutputFiles = val;
   else if(what == "merge")
     CTX::instance()->solver.autoMergeFile = val;
   else if(what == "hide")
@@ -732,7 +734,7 @@ onelabWindow::onelabWindow(int deltaFontSize)
 
   _gear->add("Save database automatically", 0, onelab_option_cb, (void*)"save",
              FL_MENU_TOGGLE);
-  _gear->add("Archive solutions automatically", 0, onelab_option_cb, (void*)"archive",
+  _gear->add("Archive output files automatically", 0, onelab_option_cb, (void*)"archive",
              FL_MENU_TOGGLE);
   _gear->add("Remesh automatically", 0, onelab_option_cb, (void*)"mesh",
              FL_MENU_TOGGLE);
@@ -1184,7 +1186,7 @@ void onelabWindow::rebuildSolverList()
   _title = "OneLab";
   Fl_Menu_Item* menu = (Fl_Menu_Item*)_gear->menu();
   int values[6] = {CTX::instance()->solver.autoSaveDatabase,
-                   CTX::instance()->solver.autoArchiveSolutions,
+                   CTX::instance()->solver.autoArchiveOutputFiles,
                    CTX::instance()->solver.autoMesh,
                    CTX::instance()->solver.autoMergeFile,
                    CTX::instance()->solver.autoHideNewViews,
diff --git a/Geo/GeoStringInterface.cpp b/Geo/GeoStringInterface.cpp
index 32f7c9f134..49d6db5819 100644
--- a/Geo/GeoStringInterface.cpp
+++ b/Geo/GeoStringInterface.cpp
@@ -20,6 +20,10 @@
 #include "Parser.h"
 #endif
 
+#if defined(HAVE_ONELAB)
+#include "onelab.h"
+#endif
+
 void add_infile(std::string text, std::string fileName, bool forceDestroy)
 {
   // make sure we don't add stuff in a non-geo file
@@ -97,6 +101,12 @@ void add_infile(std::string text, std::string fileName, bool forceDestroy)
 #else
   Msg::Error("GEO file creation not available without Gmsh parser");
 #endif
+
+  // mark all Gmsh data as changed in onelab (will force e.g. a reload and a
+  // remesh)
+#if defined(HAVE_ONELAB)
+  onelab::server::instance()->setChanged(true, "Gmsh");
+#endif
 }
 
 void coherence(std::string fileName)
diff --git a/doc/texinfo/gmsh.texi b/doc/texinfo/gmsh.texi
index d6ea87ab46..6d874e0022 100644
--- a/doc/texinfo/gmsh.texi
+++ b/doc/texinfo/gmsh.texi
@@ -1895,9 +1895,12 @@ Multiplies and affects @var{expression} to a real option.
 @item @var{real-option} /= @var{expression};
 Divides and affects @var{expression} to a real option.
 
-@item Exit;
+@item Abort;
 Aborts the current script.
 
+@item Exit;
+Exits Gmsh.
+
 @item Printf ( @var{char-expression} <, @var{expression-list}> );
 Prints a character expression in the information window and/or on the
 terminal. @code{Printf} is equivalent to the @code{printf} C function:
diff --git a/utils/misc/gmsh_app.plist b/utils/misc/gmsh_app.plist
index ef82fe9cb0..e4558442ff 100644
--- a/utils/misc/gmsh_app.plist
+++ b/utils/misc/gmsh_app.plist
@@ -39,6 +39,15 @@
         <key>CFBundleTypeOSTypes</key><array><string>GMSH</string></array>
         <key>CFBundleTypeRole</key><string>Viewer</string>
       </dict>
+      <dict>
+        <key>CFBundleTypeExtensions</key><array>
+          <string>pro</string>
+          <string>ol</string></array>
+        <key>CFBundleTypeIconFile</key><string>GmshPos.icns</string>
+        <key>CFBundleTypeName</key><string>Gmsh Solver File</string>
+        <key>CFBundleTypeOSTypes</key><array><string>GSOL</string></array>
+        <key>CFBundleTypeRole</key><string>Viewer</string>
+      </dict>
       <dict>
         <key>CFBundleTypeExtensions</key><array>
           <string>pos</string>
-- 
GitLab