From a2044153bc3b01885297cdcc4ebaeef11f084c9a Mon Sep 17 00:00:00 2001
From: Christophe Geuzaine <cgeuzaine@ulg.ac.be>
Date: Sun, 7 Mar 2010 16:59:03 +0000
Subject: [PATCH] prototype "-watch" option to watch for specific files
 according to a pattern (use 'w' shortcut in GUI to test)

---
 Common/CommandLine.cpp   |  7 +++++++
 Common/Context.h         |  2 ++
 Common/DefaultOptions.h  |  3 +++
 Common/Options.cpp       |  7 +++++++
 Common/Options.h         |  1 +
 Fltk/FlGui.cpp           |  4 ++++
 Fltk/menuWindow.cpp      | 36 ++++++++++++++++++++++++++++++++++++
 Fltk/menuWindow.h        |  1 +
 Post/PViewData.h         |  4 ++--
 Post/PViewDataGModel.cpp |  6 ++++++
 Post/PViewDataGModel.h   |  1 +
 11 files changed, 70 insertions(+), 2 deletions(-)

diff --git a/Common/CommandLine.cpp b/Common/CommandLine.cpp
index 68fdd37490..aa5c05b6da 100644
--- a/Common/CommandLine.cpp
+++ b/Common/CommandLine.cpp
@@ -231,6 +231,13 @@ void GetOptions(int argc, char *argv[])
         CTX::instance()->noPopup = 1;
         i++;
       }
+      else if(!strcmp(argv[i] + 1, "watch")) {
+        i++;
+        if(argv[i])
+          CTX::instance()->watchFilePattern = argv[i++];
+        else
+          Msg::Fatal("Missing string");
+      }
       else if(!strcmp(argv[i] + 1, "string")) {
         i++;
         if(argv[i])
diff --git a/Common/Context.h b/Common/Context.h
index 85d3d73a78..6064141bc7 100644
--- a/Common/Context.h
+++ b/Common/Context.h
@@ -82,6 +82,8 @@ class CTX {
   int numWindows, numTiles;
   // text editor and web browser command (with included '%s')
   std::string editor, webBrowser;
+  // pattern of files to watch out for
+  std::string watchFilePattern;
   // show tootips in the GUI?
   int tooltips;
   // scroll automatically to last message in the message window?
diff --git a/Common/DefaultOptions.h b/Common/DefaultOptions.h
index b711a63205..522136ea01 100644
--- a/Common/DefaultOptions.h
+++ b/Common/DefaultOptions.h
@@ -97,6 +97,9 @@ StringXString GeneralOptions_String[] = {
 #endif
     "System command to launch a web browser" },
 
+  { F|S, "WatchFilePattern", opt_general_watch_file_pattern , "" ,
+    "Pattern of files to watch out for (to load automatically)"},
+
   { 0, 0 , 0 , "" , 0 }
 } ;
 
diff --git a/Common/Options.cpp b/Common/Options.cpp
index d3b313aad0..16b5729e41 100644
--- a/Common/Options.cpp
+++ b/Common/Options.cpp
@@ -1046,6 +1046,13 @@ std::string opt_general_web_browser(OPT_ARGS_STR)
   return CTX::instance()->webBrowser;
 }
 
+std::string opt_general_watch_file_pattern(OPT_ARGS_STR)
+{
+  if(action & GMSH_SET)
+    CTX::instance()->watchFilePattern = val;
+  return CTX::instance()->watchFilePattern;
+}
+
 std::string opt_general_gui_theme(OPT_ARGS_STR)
 {
   if(action & GMSH_SET)
diff --git a/Common/Options.h b/Common/Options.h
index 5dc83d1049..834d029a7a 100644
--- a/Common/Options.h
+++ b/Common/Options.h
@@ -46,6 +46,7 @@ std::string opt_general_recent_file4(OPT_ARGS_STR);
 std::string opt_general_recent_file5(OPT_ARGS_STR);
 std::string opt_general_editor(OPT_ARGS_STR);
 std::string opt_general_web_browser(OPT_ARGS_STR);
+std::string opt_general_watch_file_pattern(OPT_ARGS_STR);
 std::string opt_general_gui_theme(OPT_ARGS_STR);
 std::string opt_general_graphics_font(OPT_ARGS_STR);
 std::string opt_solver_socket_name(OPT_ARGS_STR);
diff --git a/Fltk/FlGui.cpp b/Fltk/FlGui.cpp
index 9a509bf2fd..a350644cc3 100644
--- a/Fltk/FlGui.cpp
+++ b/Fltk/FlGui.cpp
@@ -340,6 +340,10 @@ int FlGui::testGlobalShortcuts(int event)
     mod_forward_cb(0, 0);
     status = 1;
   }
+  else if(Fl::test_shortcut('w')) {
+    file_watch_cb(0, 0);
+    status = 1;
+  }
   else if(Fl::test_shortcut('e')) {
     for(unsigned int i = 0; i < graph.size(); i++)
       for(unsigned int j = 0; j < graph[i]->gl.size(); j++)
diff --git a/Fltk/menuWindow.cpp b/Fltk/menuWindow.cpp
index 73b2afa38f..d2a503e814 100644
--- a/Fltk/menuWindow.cpp
+++ b/Fltk/menuWindow.cpp
@@ -4,10 +4,12 @@
 // bugs and problems to <gmsh@geuz.org>.
 
 #include <string.h>
+#include <stdlib.h>
 #include <stdio.h>
 #include <time.h>
 #include <FL/Fl_Box.H>
 #include <FL/fl_ask.H>
+#include <FL/filename.H>
 #include "GmshConfig.h"
 #include "GmshMessage.h"
 #include "GmshSocket.h"
@@ -413,6 +415,40 @@ void file_quit_cb(Fl_Widget *w, void *data)
   Msg::Exit(0);
 }
 
+void file_watch_cb(Fl_Widget *w, void *data)
+{
+  std::string pattern = FixRelativePath
+    (GModel::current()->getFileName(), CTX::instance()->watchFilePattern);
+  std::string directory = SplitFileName(pattern)[0];
+  if(directory.empty()) directory = "./";
+  
+  dirent **files = 0;
+  int num = fl_filename_list(directory.c_str(), &files, fl_numericsort);
+  if(num <= 0) return;
+  std::vector<std::string> matches;
+  for (int i = 0; i < num; i++) {
+    std::string name = directory + files[i]->d_name;
+    if(fl_filename_match(name.c_str(), pattern.c_str()))
+      matches.push_back(name);
+    free((void*)files[i]);
+  }
+  if(files) free((void*)files);
+
+  Msg::Info("%d files matching watch pattern '%s'", num, pattern.c_str());
+  
+  std::set<std::string> allFiles;
+  for(unsigned int i = 0; i < GModel::list.size(); i++)
+    allFiles.insert(GModel::list[i]->getFileName());
+  for(unsigned int i = 0; i < PView::list.size(); i++)
+    for(unsigned int j = 0; j < PView::list[i]->getData()->getNumTimeSteps(); j++)
+      allFiles.insert(PView::list[i]->getData()->getFileName(j));
+
+  for(unsigned int i = 0; i < matches.size(); i++)
+    if(allFiles.find(matches[i]) == allFiles.end())
+      MergeFile(matches[i]);
+  drawContext::global()->draw();
+}
+
 #if defined(__APPLE__)
 #  define CC(str) "Cmd+" str " "
 #else
diff --git a/Fltk/menuWindow.h b/Fltk/menuWindow.h
index 9f5f626bf1..14b6ab8277 100644
--- a/Fltk/menuWindow.h
+++ b/Fltk/menuWindow.h
@@ -80,6 +80,7 @@ class menuWindow{
 };
 
 void file_quit_cb(Fl_Widget *w, void *data);
+void file_watch_cb(Fl_Widget *w, void *data);
 void mod_geometry_cb(Fl_Widget *w, void *data);
 void mod_mesh_cb(Fl_Widget *w, void *data);
 void mod_solver_cb(Fl_Widget *w, void *data);
diff --git a/Post/PViewData.h b/Post/PViewData.h
index e1bc38187a..ab542330d5 100644
--- a/Post/PViewData.h
+++ b/Post/PViewData.h
@@ -51,8 +51,8 @@ class PViewData {
   virtual std::string getName(){ return _name; }
   virtual void setName(std::string val){ _name = val; }
 
-  // get/set filename
-  virtual std::string getFileName(){ return _fileName; }
+  // get/set (the main) filename containing the data
+  virtual std::string getFileName(int step=-1){ return _fileName; }
   virtual void setFileName(std::string val){ _fileName = val; }
 
   // get/set index of view data in file
diff --git a/Post/PViewDataGModel.cpp b/Post/PViewDataGModel.cpp
index d915edf87e..e9cbbca998 100644
--- a/Post/PViewDataGModel.cpp
+++ b/Post/PViewDataGModel.cpp
@@ -112,6 +112,12 @@ MElement *PViewDataGModel::_getElement(int step, int ent, int ele)
   return curr;
 }
 
+std::string PViewDataGModel::getFileName(int step)
+{
+  if(step < 0 || step > _steps.size() - 1) return PViewData::getFileName();
+  return _steps[step]->getFileName();
+}
+
 int PViewDataGModel::getNumTimeSteps()
 {
   return _steps.size();
diff --git a/Post/PViewDataGModel.h b/Post/PViewDataGModel.h
index 50aed8fd9c..293c79b344 100644
--- a/Post/PViewDataGModel.h
+++ b/Post/PViewDataGModel.h
@@ -129,6 +129,7 @@ class PViewDataGModel : public PViewData {
   PViewDataGModel(DataType type=NodeData);
   ~PViewDataGModel();
   bool finalize();
+  std::string getFileName(int step=-1);
   int getNumTimeSteps();
   double getTime(int step);
   double getMin(int step=-1);
-- 
GitLab