OpenWalnut  1.5.0dev
OpenWalnut.cpp
1 //---------------------------------------------------------------------------
2 //
3 // Project: OpenWalnut ( http://www.openwalnut.org )
4 //
5 // Copyright 2009-2022 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 <iostream>
27 #include <memory>
28 #include <string>
29 #include <vector>
30 
31 #ifdef OW_BOOST_PROGRAM_OPTIONS_FIX
32 // This circumvents an issue with boost program_options. The linker complains about missing "arg".
33 namespace boost
34 {
35  namespace program_options
36  {
37  std::string arg;
38  }
39 }
40 #endif // OW_BOOST_PROGRAM_OPTIONS_FIX
41 
42 #include <boost/program_options.hpp>
43 #include <boost/filesystem.hpp>
44 
45 #include "core/common/WLogger.h"
46 #include "core/common/WIOTools.h"
47 #include "core/common/WLogStream.h"
48 #include "core/common/WThreadedRunner.h"
49 #include "core/common/WSegmentationFault.h"
50 
51 #include "WQtGui.h"
52 #include "core/WVersion.h" // NOTE: this file is auto-generated by CMAKE
53 
54 /**
55  * \mainpage OpenWalnut Inline Documentation
56  * \par
57  * http://www.openwalnut.org
58  * \par
59  * Copyright 2009-2022 The OpenWalnut Community,
60  * 2015-2022 Hochschule Worms
61  * 2009-2022 BSV at Universitaet Leipzig,
62  * 2012-2017 Nemtics & Sebastian Eichelbaum
63  * 2009-2013 MPI CBS, Leipzig, Germany.
64  * For more information see http://www.openwalnut.org/copying
65  */
66 
67 void printVersion()
68 {
69  std::cout << "OpenWalnut -- Version: " << W_VERSION << " ( http://www.openwalnut.org )"
70  << std::endl
71  << std::endl;
72 
73  std::cout <<
74  "Copyright 2009-2022 The OpenWalnut Community\n"
75  " 2015-2022 Hochschule Worms\n"
76  " 2009-2022 BSV at Universitaet Leipzig\n"
77  " 2012-2017 Nemtics & Sebastian Eichelbaum\n"
78  " 2009-2013 MPI CBS, Leipzig, Germany\n"
79  "For more information see http://www.openwalnut.org/copying\n"
80  "This program comes with ABSOLUTELY NO WARRANTY.\n"
81  "This is free software, and you are welcome to redistribute it\n"
82  "under the terms of the GNU Lesser General Public License.\n"
83  "You should have received a copy of the GNU Lesser General Public License\n"
84  "along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>." << std::endl;
85  std::cout << std::endl; // Create new line after message for clarity.
86 
87  std::cout << "Written by the OpenWalnut Community, Hochschule Worms, Nemtics, BSV@Uni-Leipzig and CNCF@MPI-CBS." << std::endl;
88 }
89 
90 /**
91  * The main routine starting up the whole application.
92  */
93 int main( int argc, char** argv )
94 {
96 
97  // where to write the by default?
98  std::string logFile = "openwalnut.log";
99 
100  // process user parameter
101  namespace po = boost::program_options; // since the namespace is far to big we use a shortcut here
102  po::options_description desc( "Options" );
103 
104  // NOTE: if you modify this, also modify the manual pages! (use help2man or do it manually) But be careful. There need
105  // to be several manual changes to be done in the manual after help2man has done its job.
106  desc.add_options()
107  ( "help,h", "Prints this help message" )
108  ( "version,v", "Prints the version information" )
109  ( "log,l", po::value< std::string >(), ( std::string( "The log-file to use. If not specified, \"" ) + logFile +
110  std::string( "\" is used in the current directory." ) ).c_str() )
111  ( "project,p", po::value< std::string >(), "Project file to be loaded on startup." )
112  ( "input,i", po::value< std::vector< std::string > >(), "Input data files that should be loaded automatically" );
113 
114  po::positional_options_description pOptDesc;
115  pOptDesc.add( "input", -1 );
116 
117  boost::program_options::variables_map optionsMap;
118  try
119  {
120  po::store( po::command_line_parser( argc, argv ).options( desc ).positional( pOptDesc ).run(), optionsMap );
121  }
122  catch( const po::error &e )
123  {
124  std::cerr << e.what() << std::endl;
125  return -1;
126  }
127 
128  po::notify( optionsMap );
129 
130  // print usage information if command line asks for help.
131  if( optionsMap.count( "help" ) )
132  {
133  // NOTE: if you modify this, check that help2man still works properly! (http://www.gnu.org/software/help2man) But be careful. There need
134  // to be several manual changes to be done in the manual after help2man has done its job.
135  std::cout << "OpenWalnut is a highly expansible visualization system with focus on brain- and neurological data." << std::endl
136  << std::endl
137  << "Usage: openwalnut [OPTION]... [FILE]..." << std::endl
138  << std::endl
139  << desc << std::endl
140  << std::endl
141  << "Examples:" << std::endl
142  << " openwalnut\t\t\t\tStart OpenWalnut." << std::endl
143  << " openwalnut -p myproject.owp\t\tStart OpenWalnut and load the project." << std::endl
144  << " openwalnut t1.nii.gz fibers.fib\tStart OpenWalnut and load the two datasets." << std::endl
145  << std::endl;
146  return 0;
147  }
148  else if( optionsMap.count( "version" ) )
149  {
150  printVersion();
151  return 0;
152  }
153 
154  printVersion();
155 
156  // install signal handler as early as possible
158 
159  // initialize logger here. It will be started by the GUI with one default console stream
161 
162  // add a crash-log.
163  if( optionsMap.count( "log" ) )
164  {
165  logFile = optionsMap["log"].as< std::string >();
166  }
167 
168  // determine log paths
169  boost::filesystem::path logPath( logFile );
170  logPath = boost::filesystem::system_complete( logPath );
171  bool fallbackLog = false; // if true, the original log file could not be opened. A fallback is provided.
172  boost::filesystem::path fallbackLogFile = tempFilename( "OpenWalnutLog-%%%%%%%%.log" );
173 
174  // is the log writeable?
175  std::ofstream crashLogFile( logPath.string().c_str() );
176  if( !crashLogFile.is_open() )
177  {
178  // try to create fallback
179  crashLogFile.open( fallbackLogFile.string().c_str() );
180  fallbackLog = true;
181  }
182 
183  // create log stream
184  if( crashLogFile.is_open() )
185  {
186  // create the WLogStream. Set special format and DISABLE colors.
187  WLogStream::SharedPtr crashLog = WLogStream::SharedPtr( new WLogStream( crashLogFile, LL_DEBUG, "%t %l %s: %m\n", false ) );
188  WLogger::getLogger()->addStream( crashLog );
189 
190  // NOTE: the stream flushes after each entry. This is needed if a crash occurs.
191  if( !fallbackLog )
192  {
193  wlog::info( "Walnut" ) << "Using the file \"" << logPath.string() << "\" for logging.";
194  }
195  else
196  {
197  wlog::info( "Walnut" ) << "Using the fallback file \"" << fallbackLogFile.string() << "\" for logging.";
198  }
199  }
200  else
201  {
202  wlog::warn( "Walnut" ) << "Could not open \"" << logPath.string() << "\" for writing. You will have no log-file.";
203  }
204 
205  // the kernel, and the gui should print their version info. This helps processing crashlogs from users.
206  wlog::info( "Walnut" ) << "Version: " << W_VERSION;
207 
208  // Help Qt find the platform specific libs/dlls
209  #ifdef _WIN32
210  QCoreApplication::addLibraryPath( "../libExt/qtPlugins" );
211  QCoreApplication::addLibraryPath( "libExt/qtPlugins" );
212  #endif
213 
214  // initialize GUI
215  // NOTE: we need a shared_ptr here since WUI uses enable_shared_from_this.
216  std::shared_ptr< WQtGui > gui( new WQtGui( optionsMap, argc, argv ) );
217 
218  // Start GUI
219  int result = gui->run();
220 
221  std::cout << "Closed OpenWalnut smoothly. Goodbye!" << std::endl;
222 
223  return result;
224 }
Class implementing a capsule for an output stream and the needed level and format information.
Definition: WLogStream.h:39
std::shared_ptr< WLogStream > SharedPtr
shared pointer type
Definition: WLogStream.h:41
static void startup(std::ostream &output=std::cout, LogLevel level=LL_DEBUG)
Create the first and only instance of the logger as it is a singleton.
Definition: WLogger.cpp:41
static WLogger * getLogger()
Returns pointer to the currently running logger instance.
Definition: WLogger.cpp:64
void addStream(WLogStream::SharedPtr s)
Adds a new stream to the logger.
Definition: WLogger.cpp:116
The QT Based GUI implementation.
Definition: WQtGui.h:56
static void installSignalHandler()
Installs this exception as signal handler for SIGSEGV.
static void setThisThreadName(std::string name)
Static function to set the name of the calling thread.
WStreamedLogger warn(const std::string &source)
Logging a warning message.
Definition: WLogger.h:309
WStreamedLogger info(const std::string &source)
Logging an information message.
Definition: WLogger.h:320