OpenWalnut  1.5.0dev
WScriptUI.cpp
1 //---------------------------------------------------------------------------
2 //
3 // Project: OpenWalnut ( http://www.openwalnut.org )
4 //
5 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
6 // For more information see http://www.openwalnut.org/copying
7 //
8 // This file is part of OpenWalnut.
9 //
10 // OpenWalnut is free software: you can redistribute it and/or modify
11 // it under the terms of the GNU Lesser General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // OpenWalnut is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public License
21 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
22 //
23 //---------------------------------------------------------------------------
24 
25 #include <fstream>
26 #include <memory>
27 #include <sstream>
28 #include <string>
29 #include <vector>
30 
31 #include <boost/algorithm/string.hpp>
32 #include <boost/algorithm/string/predicate.hpp>
33 
34 #include "WScriptUI.h"
35 #include "core/common/WIOTools.h"
36 #include "core/common/WLogStream.h"
37 #include "core/common/WLogger.h"
38 #include "core/common/WPathHelper.h"
39 #include "core/common/WSegmentationFault.h"
40 #include "core/common/WThreadedRunner.h"
41 #include "core/kernel/WKernel.h"
42 #include "core/kernel/WModuleFactory.h"
43 
44 WScriptUI::WScriptUI( int argc, char** argv, boost::program_options::variables_map const& options )
45  : WUI( argc, argv ),
46  m_programOptions( options )
47 {
48 }
49 
51 {
52 }
53 
55 {
56  // the call path of the application
57  boost::filesystem::path walnutBin = boost::filesystem::path( m_argv[ 0 ] ).parent_path();
58 
59  // TODO(reichenbach): this might not work under windows
60  boost::filesystem::path homePath = boost::filesystem::path( getenv( "HOME" ) );
61 
62  // setup path helper which provides several paths to others
63 #ifdef Q_OS_OSX
64  // apple has a special file hierarchy in so-called bundles
65  // this code determines whether we are started from a bundle context
66  // and sets the paths according to Apple's guidelines inside the bundle
67  // if( QApplication::applicationDirPath().endsWith( "/MacOS" ) )
68  {
69  // we are in a bundle
70  // TODO(mario): apply default OSX behavior of using $HOME/Library/OpenWalnut ?
71  WPathHelper::getPathHelper()->setBasePathsOSXBundle( walnutBin, homePath / ".OpenWalnut" );
72  }
73  // else
74  {
75  // assume standard behavior
76  WPathHelper::getPathHelper()->setBasePaths( walnutBin, homePath / ".OpenWalnut" );
77  }
78 #else
79  // on all other platforms, get the home directory form Qt and the path from the application binary location
80  WPathHelper::getPathHelper()->setBasePaths( walnutBin, homePath / ".OpenWalnut" );
81 #endif
82 
83  loadToolboxes( WPathHelper::getHomePath() / "config.script" );
84 
85  //----------------------------
86  // startup
87  //----------------------------
88 
89  // start the kernel
90  std::shared_ptr< WKernel > kernel( WKernel::instance( WGraphicsEngine::getGraphicsEngine(), shared_from_this() ) );
91  kernel->run();
92 
93  //--------------------------------
94  // choose interpreter to use
95  //--------------------------------
96  std::shared_ptr< WScriptInterpreter > scriptInterpreter;
97  bool executeScriptFile = false;
98 
99  // first check if a script file is to be executed
100  if( m_programOptions.count( "file" ) )
101  {
102  boost::filesystem::path scriptFile( m_programOptions[ "file" ].as< std::vector< std::string > >()[ 0 ] );
103 
104  if( !boost::filesystem::exists( scriptFile ) )
105  {
106  wlog::error( "Walnut" ) << std::string( "Could not find script file: " ) + scriptFile.string();
107  wlog::error( "Walnut" ) << "Aborting!";
108  return 1;
109  }
110 
111  std::string ext = scriptFile.extension().string();
112 
113  scriptInterpreter = WKernel::getRunningKernel()->getScriptEngine()->getInterpreterByFileExtension( ext );
114  executeScriptFile = ( scriptInterpreter != NULL );
115 
116  if( executeScriptFile )
117  {
118  // set command line parameters
119  scriptInterpreter->setParameters( m_programOptions[ "file" ].as< std::vector< std::string > >() );
120  }
121  }
122  // then check for interp parameter
123  else if( m_programOptions.count( "interp" ) )
124  {
125  scriptInterpreter = WKernel::getRunningKernel()->getScriptEngine()->getInterpreter( m_programOptions[ "interp" ].as< std::string >() );
126  }
127 
128  if( !scriptInterpreter )
129  {
130  wlog::error( "Walnut" ) << "Could not create a script interpreter.";
131  wlog::error( "Walnut" ) << "Only the following interpreters are supported in this build:";
132  for( std::size_t k = 0; k < WKernel::getRunningKernel()->getScriptEngine()->getNumInterpreters(); ++k )
133  {
134  wlog::error( "Walnut" ) << WKernel::getRunningKernel()->getScriptEngine()->getInterpreter( k )->getName()
135  << " (" << WKernel::getRunningKernel()->getScriptEngine()->getInterpreter( k )->getExtension() << ")";
136  }
137  wlog::error( "Walnut" ) << "If the interpreter you want to use is not listed, it is either not implemented yet"
138  << " or dependencies are missing.";
139  return 1;
140  }
141 
142  // now we are initialized
143  m_isInitialized( true );
144 
145  // execute
146  if( executeScriptFile )
147  {
148  // execute provided script file
149  scriptInterpreter->executeFile( m_programOptions[ "file" ].as< std::vector< std::string > >()[ 0 ] );
150  }
151  else
152  {
153  // get lines to interpret from the user via console
154  while( true )
155  {
156  std::string in;
157  std::cout << ">>";
158  std::getline( std::cin, in );
159 
160  if( in == "quit" )
161  {
162  break;
163  }
164  else if( in == "help" )
165  {
166  in += "()";
167  }
168  else if( in == "help" )
169  {
170  in += "()";
171  }
172 
173  try
174  {
175  scriptInterpreter->execute( in );
176  }
177  catch( WException const& e )
178  {
179  wlog::error( "Walnut" ) << "Error while executing script: " << e.what();
180  break;
181  }
182  }
183  }
184 
185  // delete interpreter pointer
186  scriptInterpreter.reset();
187 
188  // signal everybody to shut down properly.
189  WKernel::getRunningKernel()->wait( true );
190 
191  // TODO(reichenbach): waiting for the graphics engine to stop will result in a deadlock; why?
192  // WKernel::getRunningKernel()->getGraphicsEngine()->wait( true );
193 
194  return 0;
195 }
196 
197 void WScriptUI::loadToolboxes( boost::filesystem::path configPath )
198 {
199  // add additional module paths to the PathHelper, the rest will be done by module loader
200  if( boost::filesystem::exists( configPath ) )
201  {
202  wlog::info( "Walnut" ) << "Reading config file from: " << configPath;
203  std::ifstream is( configPath.string().c_str() );
204  std::string line;
205  std::string pattern = "additionalModulePaths="; // same pattern in config.qt4gui file, so you may use symlinks
206  while( std::getline( is, line ) )
207  {
208  if( boost::starts_with( line, pattern ) )
209  {
210  std::istringstream ss( line.substr( pattern.size(), line.size() - pattern.size() ) );
211  std::string path;
212  while( std::getline( ss, path, ',' ) )
213  {
214  boost::algorithm::trim( path );
215  WPathHelper::getPathHelper()->addAdditionalModulePath( path );
216  // wlog::debug( "Walnut" ) << "Added: " << path << " to PathHelper";
217  }
218  break;
219  }
220  }
221  }
222 }
223 
225 {
226  return WUIWidgetFactory::SPtr();
227 }
Basic exception handler.
Definition: WException.h:39
virtual const char * what() const
Returns the message string set on throw.
Definition: WException.cpp:90
static std::shared_ptr< WGraphicsEngine > getGraphicsEngine()
Returns instance of the graphics engine.
static WKernel * getRunningKernel()
Returns pointer to the currently running kernel.
Definition: WKernel.cpp:117
static WKernel * instance(std::shared_ptr< WGraphicsEngine > ge, std::shared_ptr< WUI > ui)
Returns pointer to the running kernel or a new if no kernel was there.
Definition: WKernel.cpp:82
std::shared_ptr< WScriptEngine > getScriptEngine()
Get the script engine of this kernel.
Definition: WKernel.cpp:219
static boost::filesystem::path getHomePath()
The path to the OW dir in the user's home.
static std::shared_ptr< WPathHelper > getPathHelper()
Returns instance of the path helper.
Definition: WPathHelper.cpp:52
WScriptUI(int argc, char **argv, boost::program_options::variables_map const &options)
Constructor.
Definition: WScriptUI.cpp:44
virtual ~WScriptUI()
Destructor.
Definition: WScriptUI.cpp:50
virtual WUIWidgetFactory::SPtr getWidgetFactory() const
Returns the widget factory of the UI.
Definition: WScriptUI.cpp:224
boost::program_options::variables_map const & m_programOptions
The programm options.
Definition: WScriptUI.h:85
virtual int run()
Runs the UI.
Definition: WScriptUI.cpp:54
virtual void loadToolboxes(boost::filesystem::path configPath)
If you need to load additional modules from your toolboxes, you might want specify these paths in a c...
Definition: WScriptUI.cpp:197
void wait(bool requestFinish=false)
Wait for the thread to be finished.
std::shared_ptr< WUIWidgetFactory > SPtr
Convenience typedef for a std::shared_ptr< WUIWidgetFactory >.
This class prescribes the interface to the UI.
Definition: WUI.h:51
char ** m_argv
Command line arguments given.
Definition: WUI.h:100
WFlag< bool > m_isInitialized
Flag determining whether the UI is properly initialized.
Definition: WUI.h:90
WStreamedLogger info(const std::string &source)
Logging an information message.
Definition: WLogger.h:320
WStreamedLogger error(const std::string &source)
Logging an error message.
Definition: WLogger.h:298