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
Line 
1/*
2 * Project: MoleCuilder
3 * Description: creates and alters molecular systems
4 * Copyright (C) 2010-2012 University of Bonn. All rights reserved.
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/>.
21 */
22
23/*
24 * QtUIFactory.cpp
25 *
26 * Created on: Jan 14, 2010
27 * Author: crueger
28 */
29
30// include config.h
31#ifdef HAVE_CONFIG_H
32#include <config.h>
33#endif
34
35#include <cassert>
36#include <iostream>
37#include <fstream>
38#include <string.h>
39
40#include <boost/filesystem/path.hpp>
41
42#include <Qt/qapplication.h>
43
44
45#include "UIElements/Qt4/QtUIFactory.hpp"
46#include "UIElements/Qt4/QtMainWindow.hpp"
47#include "UIElements/Qt4/QtDialog.hpp"
48
49// boost::python uses placement new which is incompatible with MemDebug.
50#ifdef HAVE_PYTHON
51#include "Python/PythonScripting.hpp"
52#endif
53
54//#include "CodePatterns/MemDebug.hpp"
55
56#include "Actions/ActionQueue.hpp"
57#include "Helpers/defs.hpp"
58
59using namespace std;
60
61QtUIFactory::QtUIFactory(int _argc, char **_argv) :
62 argc(0),
63 argv(NULL),
64 testlauncher_Interrupted(false),
65 testlauncher_thread(NULL)
66{
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);
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;
80 scripts.reserve(1);
81 scripts.push_back(std::string(_argv[2]));
82
83 // check for line-by-line execution
84 const bool SingleLineStepping = (strncmp(&_argv[1][7], "single", 6) == 0);
85
86 // prepare an extra thread
87 std::cout << "TESTLAUNCHER: Preparing " << std::endl;
88 testlauncher_thread = new boost::thread(
89 boost::bind(&QtUIFactory::testrun, this, scripts, SingleLineStepping));
90#else
91 std::cerr << "Boost::thread support missing! Cannot launch test scripts.\n";
92#endif
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 }
105 app = new QApplication(argc,argv);
106 } else {
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 }
114 app = new QApplication(argc,argv);
115 }
116}
117
118QtUIFactory::~QtUIFactory()
119{
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;
131}
132
133Dialog* QtUIFactory::makeDialog(const std::string &_title) {
134 return new QtDialog(_title);
135}
136
137MainWindow* QtUIFactory::makeMainWindow() {
138 MainWindow * const mainwindow = new QtMainWindow(app);
139 UIFactory::doneInitializing = true;
140 return mainwindow;
141}
142
143QtUIFactory::description::description(int _argc, char **_argv) :
144 UIFactory::factoryDescription("Qt4"),
145 argc(_argc),
146 argv(_argv)
147{}
148
149QtUIFactory::description::~description()
150{}
151
152UIFactory* QtUIFactory::description::makeFactory(){
153 return new QtUIFactory(argc, argv);
154}
155
156bool QtUIFactory::isTestMode(const char *_argument)
157{
158 return (strncmp(_argument,"--test", 6) == 0);
159}
160
161bool QtUIFactory::isGuiMode(const char *_argument)
162{
163 return (strncmp(_argument,"--qt_size", 9) == 0) || (strncmp(_argument,"--qt_position", 13) == 0);
164}
165
166void QtUIFactory::testrun(const std::vector<std::string> _scripts, const bool _singleLineStepping) const
167{
168 std::cout << "TESTLAUNCHER: Waiting for GUI to set up" << std::endl;
169 while (!UIFactory::isDoneInitializing())
170 testlauncher_sleep(boost::posix_time::milliseconds(100));
171
172 std::vector<std::string>::const_iterator scriptiter = _scripts.begin();
173 do {
174 // then launch script
175 std::cout << "TESTLAUNCHER: Launching script " << *scriptiter
176 << (_singleLineStepping ? " line by line." : ".") <<std::endl;
177#ifdef HAVE_PYTHON
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);
190 do {
191 app->processEvents();
192 testlauncher_sleep(boost::posix_time::milliseconds(100));
193 } while (!MoleCuilder::ActionQueue::getInstance().isIdle());
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 }
200 }
201 } else {
202 executePythonScriptFile(*scriptiter);
203 }
204#else
205 std::cerr << "Python support not compiled in, cannot execute gui test scripts.\n";
206#endif
207 ++scriptiter;
208
209 std::cout << "TESTLAUNCHER: Sleeping after script" << std::endl;
210 testlauncher_sleep(boost::posix_time::milliseconds(200));
211
212 } while ((scriptiter != _scripts.end()) && (!testlauncher_Interrupted));
213
214 // send quit signal
215 std::cout << "TESTLAUNCHER: Quitting" << std::endl;
216 app->quit(); // exit flag here is not relevant, end of main() sets the return code
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
226 boost::this_thread::sleep_for(boost::chrono::milliseconds(500));
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.