| [bcf653] | 1 | /*
 | 
|---|
 | 2 |  * Project: MoleCuilder
 | 
|---|
 | 3 |  * Description: creates and alters molecular systems
 | 
|---|
| [0aa122] | 4 |  * Copyright (C)  2010-2012 University of Bonn. All rights reserved.
 | 
|---|
| [94d5ac6] | 5 |  * 
 | 
|---|
 | 6 |  *
 | 
|---|
 | 7 |  *   This file is part of MoleCuilder.
 | 
|---|
 | 8 |  *
 | 
|---|
 | 9 |  *    MoleCuilder is free software: you can redistribute it and/or modify
 | 
|---|
 | 10 |  *    it under the terms of the GNU General Public License as published by
 | 
|---|
 | 11 |  *    the Free Software Foundation, either version 2 of the License, or
 | 
|---|
 | 12 |  *    (at your option) any later version.
 | 
|---|
 | 13 |  *
 | 
|---|
 | 14 |  *    MoleCuilder is distributed in the hope that it will be useful,
 | 
|---|
 | 15 |  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
|---|
 | 16 |  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
|---|
 | 17 |  *    GNU General Public License for more details.
 | 
|---|
 | 18 |  *
 | 
|---|
 | 19 |  *    You should have received a copy of the GNU General Public License
 | 
|---|
 | 20 |  *    along with MoleCuilder.  If not, see <http://www.gnu.org/licenses/>.
 | 
|---|
| [bcf653] | 21 |  */
 | 
|---|
 | 22 | 
 | 
|---|
| [ea94a8] | 23 | /*
 | 
|---|
| [4cf323d] | 24 |  * QtUIFactory.cpp
 | 
|---|
| [ea94a8] | 25 |  *
 | 
|---|
 | 26 |  *  Created on: Jan 14, 2010
 | 
|---|
 | 27 |  *      Author: crueger
 | 
|---|
 | 28 |  */
 | 
|---|
 | 29 | 
 | 
|---|
| [bbbad5] | 30 | // include config.h
 | 
|---|
 | 31 | #ifdef HAVE_CONFIG_H
 | 
|---|
 | 32 | #include <config.h>
 | 
|---|
 | 33 | #endif
 | 
|---|
 | 34 | 
 | 
|---|
| [ea94a8] | 35 | #include <cassert>
 | 
|---|
| [3054689] | 36 | #include <iostream>
 | 
|---|
| [08d042] | 37 | #include <fstream>
 | 
|---|
| [3054689] | 38 | #include <string.h>
 | 
|---|
| [ea94a8] | 39 | 
 | 
|---|
| [15e197] | 40 | #include <boost/filesystem/path.hpp>
 | 
|---|
 | 41 | 
 | 
|---|
| [4269ca] | 42 | #include <Qt/qapplication.h>
 | 
|---|
| [8f67e2] | 43 | 
 | 
|---|
| [bbbad5] | 44 | 
 | 
|---|
| [4cf323d] | 45 | #include "UIElements/Qt4/QtUIFactory.hpp"
 | 
|---|
 | 46 | #include "UIElements/Qt4/QtMainWindow.hpp"
 | 
|---|
 | 47 | #include "UIElements/Qt4/QtDialog.hpp"
 | 
|---|
| [bbbad5] | 48 | 
 | 
|---|
| [15e197] | 49 | // boost::python uses placement new which is incompatible with MemDebug.
 | 
|---|
 | 50 | #ifdef HAVE_PYTHON
 | 
|---|
 | 51 | #include "Python/PythonScripting.hpp"
 | 
|---|
 | 52 | #endif
 | 
|---|
 | 53 | 
 | 
|---|
| [9eb71b3] | 54 | //#include "CodePatterns/MemDebug.hpp"
 | 
|---|
| [bbbad5] | 55 | 
 | 
|---|
| [a87d1e2] | 56 | #include "Actions/ActionQueue.hpp"
 | 
|---|
| [e4fe8d] | 57 | #include "Helpers/defs.hpp"
 | 
|---|
| [bbbad5] | 58 | 
 | 
|---|
 | 59 | using namespace std;
 | 
|---|
| [ea94a8] | 60 | 
 | 
|---|
| [15e197] | 61 | QtUIFactory::QtUIFactory(int _argc, char **_argv) :
 | 
|---|
 | 62 |     argc(1),
 | 
|---|
 | 63 |     argv(new char*[1]),
 | 
|---|
 | 64 |     testlauncher_Interrupted(false),
 | 
|---|
 | 65 |     testlauncher_thread(NULL)
 | 
|---|
| [ea94a8] | 66 | {
 | 
|---|
| [15e197] | 67 | 
 | 
|---|
 | 68 |   // check whether we are in test mode
 | 
|---|
 | 69 |   if ((_argc > 1) && (isTestMode(_argv[1]))) {
 | 
|---|
 | 70 | #ifdef HAVE_BOOST_THREAD_HPP
 | 
|---|
 | 71 |     std::vector<std::string> scripts;
 | 
|---|
 | 72 |     scripts.reserve(_argc-1);
 | 
|---|
 | 73 |     for (int i=2;i<_argc;++i)
 | 
|---|
 | 74 |       scripts.push_back(std::string(_argv[i]));
 | 
|---|
 | 75 | 
 | 
|---|
| [08d042] | 76 |     // check for line-by-line execution
 | 
|---|
| [883ea0] | 77 |     const bool SingleLineStepping = (strncmp(&_argv[1][7], "single", 6) == 0);
 | 
|---|
| [08d042] | 78 | 
 | 
|---|
| [15e197] | 79 |     // prepare an extra thread
 | 
|---|
 | 80 |     std::cout << "TESTLAUNCHER: Preparing " << std::endl;
 | 
|---|
 | 81 |     testlauncher_thread = new boost::thread(
 | 
|---|
| [08d042] | 82 |         boost::bind(&QtUIFactory::testrun, this, scripts, SingleLineStepping));
 | 
|---|
| [15e197] | 83 | #else
 | 
|---|
 | 84 |     std::cerr << "Boost::thread support missing! Cannot launch test scripts.\n";
 | 
|---|
 | 85 | #endif
 | 
|---|
 | 86 |     // use fake commands to not pass test stuff
 | 
|---|
 | 87 |     const int length = strlen(_argv[0]);
 | 
|---|
 | 88 |     argv[0] = new char[length];
 | 
|---|
| [9ad4d6] | 89 |     strncpy(argv[0],_argv[0], length);
 | 
|---|
| [15e197] | 90 |     app = new QApplication(argc,argv);
 | 
|---|
 | 91 |   } else {
 | 
|---|
| [5284ff] | 92 |     const int length = strlen(_argv[0]);
 | 
|---|
 | 93 |     argv[0] = new char[length];
 | 
|---|
 | 94 |     strncpy(argv[0],_argv[0], length);
 | 
|---|
 | 95 |     app = new QApplication(argc,argv);
 | 
|---|
| [15e197] | 96 |   }
 | 
|---|
| [ea94a8] | 97 | }
 | 
|---|
 | 98 | 
 | 
|---|
| [4cf323d] | 99 | QtUIFactory::~QtUIFactory()
 | 
|---|
| [ea94a8] | 100 | {
 | 
|---|
| [15e197] | 101 |   if (testlauncher_thread != NULL) {
 | 
|---|
 | 102 |     // notify testlauncher_thread thread that we wish to terminate
 | 
|---|
 | 103 |     testlauncher_thread->interrupt();
 | 
|---|
 | 104 |     // wait till it ends
 | 
|---|
 | 105 |     testlauncher_thread->join();
 | 
|---|
 | 106 |     // and remove
 | 
|---|
 | 107 |     delete testlauncher_thread;
 | 
|---|
 | 108 |   }
 | 
|---|
 | 109 |   // free fake command line argument arrays
 | 
|---|
 | 110 |   delete[] argv[0];
 | 
|---|
 | 111 |   delete[] argv;
 | 
|---|
| [ea94a8] | 112 | }
 | 
|---|
 | 113 | 
 | 
|---|
| [163110] | 114 | Dialog* QtUIFactory::makeDialog(const std::string &_title) {
 | 
|---|
 | 115 |   return new QtDialog(_title);
 | 
|---|
| [ea94a8] | 116 | }
 | 
|---|
 | 117 | 
 | 
|---|
| [4cf323d] | 118 | MainWindow* QtUIFactory::makeMainWindow() {
 | 
|---|
| [28864c] | 119 |   MainWindow * const mainwindow = new QtMainWindow(app);
 | 
|---|
 | 120 |   UIFactory::doneInitializing = true;
 | 
|---|
 | 121 |   return mainwindow;
 | 
|---|
| [ea94a8] | 122 | }
 | 
|---|
| [82b71a] | 123 | 
 | 
|---|
| [15e197] | 124 | QtUIFactory::description::description(int _argc, char **_argv) :
 | 
|---|
 | 125 |     UIFactory::factoryDescription("Qt4"),
 | 
|---|
 | 126 |     argc(_argc),
 | 
|---|
 | 127 |     argv(_argv)
 | 
|---|
| [82b71a] | 128 | {}
 | 
|---|
 | 129 | 
 | 
|---|
| [4cf323d] | 130 | QtUIFactory::description::~description()
 | 
|---|
| [82b71a] | 131 | {}
 | 
|---|
 | 132 | 
 | 
|---|
| [4cf323d] | 133 | UIFactory* QtUIFactory::description::makeFactory(){
 | 
|---|
| [15e197] | 134 |   return new QtUIFactory(argc, argv);
 | 
|---|
| [82b71a] | 135 | }
 | 
|---|
| [3054689] | 136 | 
 | 
|---|
 | 137 | bool QtUIFactory::isTestMode(const char *_argument)
 | 
|---|
 | 138 | {
 | 
|---|
 | 139 |   return (strncmp(_argument,"--test", 6) == 0);
 | 
|---|
 | 140 | }
 | 
|---|
| [15e197] | 141 | 
 | 
|---|
| [08d042] | 142 | void QtUIFactory::testrun(const std::vector<std::string> _scripts, const bool _singleLineStepping) const
 | 
|---|
| [15e197] | 143 | {
 | 
|---|
 | 144 |   std::cout << "TESTLAUNCHER: Waiting for GUI to set up" << std::endl;
 | 
|---|
| [28864c] | 145 |   while (!UIFactory::isDoneInitializing())
 | 
|---|
 | 146 |     testlauncher_sleep(boost::posix_time::seconds(.1));
 | 
|---|
| [15e197] | 147 | 
 | 
|---|
 | 148 |   std::vector<std::string>::const_iterator scriptiter = _scripts.begin();
 | 
|---|
 | 149 |   do {
 | 
|---|
 | 150 |     // then launch script
 | 
|---|
| [08d042] | 151 |     std::cout << "TESTLAUNCHER: Launching script " << *scriptiter
 | 
|---|
 | 152 |         << (_singleLineStepping ? " line by line." : ".") <<std::endl;
 | 
|---|
| [dbfb03] | 153 | #ifdef HAVE_PYTHON
 | 
|---|
| [08d042] | 154 |     if (_singleLineStepping) {
 | 
|---|
 | 155 |       boost::filesystem::path scriptfilename(*scriptiter);
 | 
|---|
 | 156 |       ASSERT( boost::filesystem::exists(scriptfilename),
 | 
|---|
 | 157 |           "QtUIFactory::testrun() - given testmode script file "
 | 
|---|
 | 158 |           +toString(scriptfilename.string())+" does not exist.");
 | 
|---|
 | 159 |       std::ifstream scriptfile(scriptfilename.string().c_str());
 | 
|---|
 | 160 |       std::string scriptfile_line;
 | 
|---|
 | 161 |       const std::string testmode("testmode, line nr.");
 | 
|---|
 | 162 |       unsigned int line_nr = 0;
 | 
|---|
 | 163 |       while(std::getline(scriptfile, scriptfile_line)) {
 | 
|---|
 | 164 |         std::string scriptname = testmode+toString(++line_nr);
 | 
|---|
 | 165 |         executePythonScript(scriptfile_line, scriptname);
 | 
|---|
| [883ea0] | 166 |         do {
 | 
|---|
| [b375e7] | 167 |           app->processEvents();
 | 
|---|
| [d845bd] | 168 |           testlauncher_sleep(boost::posix_time::seconds(.1));
 | 
|---|
| [883ea0] | 169 |         } while (!MoleCuilder::ActionQueue::getInstance().isIdle());
 | 
|---|
| [917c46] | 170 |         // check whether last action did not fail (otherwise we would reset
 | 
|---|
 | 171 |         // the ActionQueue's exitflag by adding more Actions.
 | 
|---|
 | 172 |         if (!MoleCuilder::ActionQueue::getInstance().getLastActionOk()) {
 | 
|---|
 | 173 |           std::cout << "Last Action has failed, aborting testrun." << std::endl;
 | 
|---|
 | 174 |           break;
 | 
|---|
 | 175 |         }
 | 
|---|
| [08d042] | 176 |       }
 | 
|---|
 | 177 |     } else {
 | 
|---|
 | 178 |       executePythonScriptFile(*scriptiter);
 | 
|---|
 | 179 |     }
 | 
|---|
| [dbfb03] | 180 | #else
 | 
|---|
 | 181 |     std::cerr << "Python support not compiled in, cannot execute gui test scripts.\n";
 | 
|---|
 | 182 | #endif
 | 
|---|
| [15e197] | 183 |     ++scriptiter;
 | 
|---|
 | 184 | 
 | 
|---|
 | 185 |     std::cout << "TESTLAUNCHER: Sleeping after script" << std::endl;
 | 
|---|
| [d845bd] | 186 |     testlauncher_sleep(boost::posix_time::seconds(.2));
 | 
|---|
| [15e197] | 187 | 
 | 
|---|
 | 188 |   } while ((scriptiter != _scripts.end()) && (!testlauncher_Interrupted));
 | 
|---|
 | 189 | 
 | 
|---|
 | 190 |   // send quit signal
 | 
|---|
 | 191 |   std::cout << "TESTLAUNCHER: Quitting" << std::endl;
 | 
|---|
| [c13b91] | 192 |   app->quit(); // exit flag here is not relevant, end of main() sets the return code
 | 
|---|
| [15e197] | 193 | }
 | 
|---|
 | 194 | 
 | 
|---|
 | 195 | void QtUIFactory::testlauncher_sleep(const boost::posix_time::time_duration& _period) const
 | 
|---|
 | 196 | {
 | 
|---|
 | 197 |   try {
 | 
|---|
 | 198 |     // first sleep for four seconds
 | 
|---|
 | 199 | #if BOOST_VERSION < 105000
 | 
|---|
 | 200 |     testlauncher_thread->sleep(boost::get_system_time() + _period);
 | 
|---|
 | 201 | #else
 | 
|---|
| [d845bd] | 202 |     boost::this_thread::sleep_for(boost::chrono::milliseconds(500));
 | 
|---|
| [15e197] | 203 | #endif
 | 
|---|
 | 204 |   } catch(boost::thread_interrupted &e) {
 | 
|---|
 | 205 |     LOG(2, "INFO: testlauncher thread has received stop signal.");
 | 
|---|
 | 206 |   }
 | 
|---|
 | 207 | }
 | 
|---|