source: src/UIElements/Qt4/QtUIFactory.cpp@ c41ce0

Candidate_v1.7.0 stable
Last change on this file since c41ce0 was c41ce0, checked in by Frederik Heber <frederik.heber@…>, 3 months ago

Adds qt_size and qt_position arguments to control Qt window size.

  • override is only temporary and is not stored in QSettings.
  • this allows using these parameters in scripts to take screenshots in a reliable manner but retain the actual window size for other usages.
  • Property mode set to 100644
File size: 7.1 KB
RevLine 
[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
59using namespace std;
[ea94a8]60
[15e197]61QtUIFactory::QtUIFactory(int _argc, char **_argv) :
[c41ce0]62 argc(0),
63 argv(NULL),
[15e197]64 testlauncher_Interrupted(false),
65 testlauncher_thread(NULL)
[ea94a8]66{
[44ce58]67 /** Initialises XInitThreads before starting the QApplication.
68 * see https://forum.qt.io/topic/85774/qt-application-crash/6
69 * This causes the following issues when starting molecuildergui:
70 * ```
71 * [xcb] Most likely this is a multi-threaded client and XInitThreads has not been called
72 * [xcb] Aborting, sorry about that.
73 * ```
74 */
75 QApplication::setAttribute(Qt::AA_X11InitThreads);
[15e197]76 // check whether we are in test mode
77 if ((_argc > 1) && (isTestMode(_argv[1]))) {
78#ifdef HAVE_BOOST_THREAD_HPP
79 std::vector<std::string> scripts;
[c41ce0]80 scripts.reserve(1);
81 scripts.push_back(std::string(_argv[2]));
[15e197]82
[08d042]83 // check for line-by-line execution
[883ea0]84 const bool SingleLineStepping = (strncmp(&_argv[1][7], "single", 6) == 0);
[08d042]85
[15e197]86 // prepare an extra thread
87 std::cout << "TESTLAUNCHER: Preparing " << std::endl;
88 testlauncher_thread = new boost::thread(
[08d042]89 boost::bind(&QtUIFactory::testrun, this, scripts, SingleLineStepping));
[15e197]90#else
91 std::cerr << "Boost::thread support missing! Cannot launch test scripts.\n";
92#endif
[c41ce0]93 // remove test options from command line arguments
94 argc = _argc-2;
95 argv = new char*[argc];
96 int j = 0;
97 for (int i=0;i<_argc;++i) {
98 if ((i >= 1) && (i<3))
99 continue;
100 const int length = strlen(_argv[i]);
101 argv[j] = new char[length];
102 strncpy(argv[j],_argv[i], length);
103 ++j;
104 }
[15e197]105 app = new QApplication(argc,argv);
106 } else {
[c41ce0]107 argc = _argc;
108 argv = new char*[argc];
109 for (int i=0;i<_argc;++i) {
110 const int length = strlen(_argv[i]);
111 argv[i] = new char[length];
112 strncpy(argv[i],_argv[i], length);
113 }
[5284ff]114 app = new QApplication(argc,argv);
[15e197]115 }
[ea94a8]116}
117
[4cf323d]118QtUIFactory::~QtUIFactory()
[ea94a8]119{
[15e197]120 if (testlauncher_thread != NULL) {
121 // notify testlauncher_thread thread that we wish to terminate
122 testlauncher_thread->interrupt();
123 // wait till it ends
124 testlauncher_thread->join();
125 // and remove
126 delete testlauncher_thread;
127 }
128 // free fake command line argument arrays
129 delete[] argv[0];
130 delete[] argv;
[ea94a8]131}
132
[163110]133Dialog* QtUIFactory::makeDialog(const std::string &_title) {
134 return new QtDialog(_title);
[ea94a8]135}
136
[4cf323d]137MainWindow* QtUIFactory::makeMainWindow() {
[28864c]138 MainWindow * const mainwindow = new QtMainWindow(app);
139 UIFactory::doneInitializing = true;
140 return mainwindow;
[ea94a8]141}
[82b71a]142
[15e197]143QtUIFactory::description::description(int _argc, char **_argv) :
144 UIFactory::factoryDescription("Qt4"),
145 argc(_argc),
146 argv(_argv)
[82b71a]147{}
148
[4cf323d]149QtUIFactory::description::~description()
[82b71a]150{}
151
[4cf323d]152UIFactory* QtUIFactory::description::makeFactory(){
[15e197]153 return new QtUIFactory(argc, argv);
[82b71a]154}
[3054689]155
156bool QtUIFactory::isTestMode(const char *_argument)
157{
158 return (strncmp(_argument,"--test", 6) == 0);
159}
[15e197]160
[c41ce0]161bool QtUIFactory::isGuiMode(const char *_argument)
162{
163 return (strncmp(_argument,"--qt_size", 9) == 0) || (strncmp(_argument,"--qt_position", 13) == 0);
164}
165
[08d042]166void QtUIFactory::testrun(const std::vector<std::string> _scripts, const bool _singleLineStepping) const
[15e197]167{
168 std::cout << "TESTLAUNCHER: Waiting for GUI to set up" << std::endl;
[28864c]169 while (!UIFactory::isDoneInitializing())
[c8a442]170 testlauncher_sleep(boost::posix_time::milliseconds(100));
[15e197]171
172 std::vector<std::string>::const_iterator scriptiter = _scripts.begin();
173 do {
174 // then launch script
[08d042]175 std::cout << "TESTLAUNCHER: Launching script " << *scriptiter
176 << (_singleLineStepping ? " line by line." : ".") <<std::endl;
[dbfb03]177#ifdef HAVE_PYTHON
[08d042]178 if (_singleLineStepping) {
179 boost::filesystem::path scriptfilename(*scriptiter);
180 ASSERT( boost::filesystem::exists(scriptfilename),
181 "QtUIFactory::testrun() - given testmode script file "
182 +toString(scriptfilename.string())+" does not exist.");
183 std::ifstream scriptfile(scriptfilename.string().c_str());
184 std::string scriptfile_line;
185 const std::string testmode("testmode, line nr.");
186 unsigned int line_nr = 0;
187 while(std::getline(scriptfile, scriptfile_line)) {
188 std::string scriptname = testmode+toString(++line_nr);
189 executePythonScript(scriptfile_line, scriptname);
[883ea0]190 do {
[b375e7]191 app->processEvents();
[c8a442]192 testlauncher_sleep(boost::posix_time::milliseconds(100));
[883ea0]193 } while (!MoleCuilder::ActionQueue::getInstance().isIdle());
[917c46]194 // check whether last action did not fail (otherwise we would reset
195 // the ActionQueue's exitflag by adding more Actions.
196 if (!MoleCuilder::ActionQueue::getInstance().getLastActionOk()) {
197 std::cout << "Last Action has failed, aborting testrun." << std::endl;
198 break;
199 }
[08d042]200 }
201 } else {
202 executePythonScriptFile(*scriptiter);
203 }
[dbfb03]204#else
205 std::cerr << "Python support not compiled in, cannot execute gui test scripts.\n";
206#endif
[15e197]207 ++scriptiter;
208
209 std::cout << "TESTLAUNCHER: Sleeping after script" << std::endl;
[c8a442]210 testlauncher_sleep(boost::posix_time::milliseconds(200));
[15e197]211
212 } while ((scriptiter != _scripts.end()) && (!testlauncher_Interrupted));
213
214 // send quit signal
215 std::cout << "TESTLAUNCHER: Quitting" << std::endl;
[c13b91]216 app->quit(); // exit flag here is not relevant, end of main() sets the return code
[15e197]217}
218
219void QtUIFactory::testlauncher_sleep(const boost::posix_time::time_duration& _period) const
220{
221 try {
222 // first sleep for four seconds
223#if BOOST_VERSION < 105000
224 testlauncher_thread->sleep(boost::get_system_time() + _period);
225#else
[d845bd]226 boost::this_thread::sleep_for(boost::chrono::milliseconds(500));
[15e197]227#endif
228 } catch(boost::thread_interrupted &e) {
229 LOG(2, "INFO: testlauncher thread has received stop signal.");
230 }
231}
Note: See TracBrowser for help on using the repository browser.