source: src/UIElements/Qt4/QtUIFactory.cpp@ 44ce58

Candidate_v1.7.0 stable
Last change on this file since 44ce58 was 44ce58, checked in by Frederik Heber <frederik.heber@…>, 2 years ago

FIX: solves xcb issues under ubuntu 22.04.

  • under Ubuntu 22.04 (with molecuilder compiled under ubuntu 22.04), I've encountered the following issues:
    • missing swrast and fbColor: required mesa-utils package
    • [xcb] ... missing XInitThreads() call: added Qt::AA_X11InitThreads to QApplication settings such that XInitThreads() is called before app is started.
    • X Error: GLXBadContext 170: requires xserver-xorg-video-all package.
  • Property mode set to 100644
File size: 6.7 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(1),
63 argv(new char*[1]),
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(_argc-1);
81 for (int i=2;i<_argc;++i)
82 scripts.push_back(std::string(_argv[i]));
83
84 // check for line-by-line execution
85 const bool SingleLineStepping = (strncmp(&_argv[1][7], "single", 6) == 0);
86
87 // prepare an extra thread
88 std::cout << "TESTLAUNCHER: Preparing " << std::endl;
89 testlauncher_thread = new boost::thread(
90 boost::bind(&QtUIFactory::testrun, this, scripts, SingleLineStepping));
91#else
92 std::cerr << "Boost::thread support missing! Cannot launch test scripts.\n";
93#endif
94 // use fake commands to not pass test stuff
95 const int length = strlen(_argv[0]);
96 argv[0] = new char[length];
97 strncpy(argv[0],_argv[0], length);
98 app = new QApplication(argc,argv);
99 } else {
100 const int length = strlen(_argv[0]);
101 argv[0] = new char[length];
102 strncpy(argv[0],_argv[0], length);
103 app = new QApplication(argc,argv);
104 }
105}
106
107QtUIFactory::~QtUIFactory()
108{
109 if (testlauncher_thread != NULL) {
110 // notify testlauncher_thread thread that we wish to terminate
111 testlauncher_thread->interrupt();
112 // wait till it ends
113 testlauncher_thread->join();
114 // and remove
115 delete testlauncher_thread;
116 }
117 // free fake command line argument arrays
118 delete[] argv[0];
119 delete[] argv;
120}
121
122Dialog* QtUIFactory::makeDialog(const std::string &_title) {
123 return new QtDialog(_title);
124}
125
126MainWindow* QtUIFactory::makeMainWindow() {
127 MainWindow * const mainwindow = new QtMainWindow(app);
128 UIFactory::doneInitializing = true;
129 return mainwindow;
130}
131
132QtUIFactory::description::description(int _argc, char **_argv) :
133 UIFactory::factoryDescription("Qt4"),
134 argc(_argc),
135 argv(_argv)
136{}
137
138QtUIFactory::description::~description()
139{}
140
141UIFactory* QtUIFactory::description::makeFactory(){
142 return new QtUIFactory(argc, argv);
143}
144
145bool QtUIFactory::isTestMode(const char *_argument)
146{
147 return (strncmp(_argument,"--test", 6) == 0);
148}
149
150void QtUIFactory::testrun(const std::vector<std::string> _scripts, const bool _singleLineStepping) const
151{
152 std::cout << "TESTLAUNCHER: Waiting for GUI to set up" << std::endl;
153 while (!UIFactory::isDoneInitializing())
154 testlauncher_sleep(boost::posix_time::milliseconds(100));
155
156 std::vector<std::string>::const_iterator scriptiter = _scripts.begin();
157 do {
158 // then launch script
159 std::cout << "TESTLAUNCHER: Launching script " << *scriptiter
160 << (_singleLineStepping ? " line by line." : ".") <<std::endl;
161#ifdef HAVE_PYTHON
162 if (_singleLineStepping) {
163 boost::filesystem::path scriptfilename(*scriptiter);
164 ASSERT( boost::filesystem::exists(scriptfilename),
165 "QtUIFactory::testrun() - given testmode script file "
166 +toString(scriptfilename.string())+" does not exist.");
167 std::ifstream scriptfile(scriptfilename.string().c_str());
168 std::string scriptfile_line;
169 const std::string testmode("testmode, line nr.");
170 unsigned int line_nr = 0;
171 while(std::getline(scriptfile, scriptfile_line)) {
172 std::string scriptname = testmode+toString(++line_nr);
173 executePythonScript(scriptfile_line, scriptname);
174 do {
175 app->processEvents();
176 testlauncher_sleep(boost::posix_time::milliseconds(100));
177 } while (!MoleCuilder::ActionQueue::getInstance().isIdle());
178 // check whether last action did not fail (otherwise we would reset
179 // the ActionQueue's exitflag by adding more Actions.
180 if (!MoleCuilder::ActionQueue::getInstance().getLastActionOk()) {
181 std::cout << "Last Action has failed, aborting testrun." << std::endl;
182 break;
183 }
184 }
185 } else {
186 executePythonScriptFile(*scriptiter);
187 }
188#else
189 std::cerr << "Python support not compiled in, cannot execute gui test scripts.\n";
190#endif
191 ++scriptiter;
192
193 std::cout << "TESTLAUNCHER: Sleeping after script" << std::endl;
194 testlauncher_sleep(boost::posix_time::milliseconds(200));
195
196 } while ((scriptiter != _scripts.end()) && (!testlauncher_Interrupted));
197
198 // send quit signal
199 std::cout << "TESTLAUNCHER: Quitting" << std::endl;
200 app->quit(); // exit flag here is not relevant, end of main() sets the return code
201}
202
203void QtUIFactory::testlauncher_sleep(const boost::posix_time::time_duration& _period) const
204{
205 try {
206 // first sleep for four seconds
207#if BOOST_VERSION < 105000
208 testlauncher_thread->sleep(boost::get_system_time() + _period);
209#else
210 boost::this_thread::sleep_for(boost::chrono::milliseconds(500));
211#endif
212 } catch(boost::thread_interrupted &e) {
213 LOG(2, "INFO: testlauncher thread has received stop signal.");
214 }
215}
Note: See TracBrowser for help on using the repository browser.