Developer Documentation
Loading...
Searching...
No Matches
OpenFlipper.cc
1/*===========================================================================*\
2* *
3* OpenFlipper *
4 * Copyright (c) 2001-2015, RWTH-Aachen University *
5 * Department of Computer Graphics and Multimedia *
6 * All rights reserved. *
7 * www.openflipper.org *
8 * *
9 *---------------------------------------------------------------------------*
10 * This file is part of OpenFlipper. *
11 *---------------------------------------------------------------------------*
12 * *
13 * Redistribution and use in source and binary forms, with or without *
14 * modification, are permitted provided that the following conditions *
15 * are met: *
16 * *
17 * 1. Redistributions of source code must retain the above copyright notice, *
18 * this list of conditions and the following disclaimer. *
19 * *
20 * 2. Redistributions in binary form must reproduce the above copyright *
21 * notice, this list of conditions and the following disclaimer in the *
22 * documentation and/or other materials provided with the distribution. *
23 * *
24 * 3. Neither the name of the copyright holder nor the names of its *
25 * contributors may be used to endorse or promote products derived from *
26 * this software without specific prior written permission. *
27 * *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39* *
40\*===========================================================================*/
41
42
43
44
45
46// Mainwindow
47
49#include "common/glew_wrappers.hh"
50#include "OpenFlipper/BasePlugin/PluginFunctionsCore.hh"
51
52// Qt
53#if QT_VERSION_MAJOR < 6
54#include <qgl.h>
55#endif
56
57// stdc++
58#include <csignal>
59#include <regex>
60
61#include <QCommandLineParser>
62
63#if ( defined(WIN32))
64 #define NO_EXECINFO
65#endif
66
67#ifndef NO_EXECINFO
68#include <execinfo.h>
69#endif
70
71#ifdef PYTHON_ENABLED
72 #include <PythonInterpreter/PythonInterpreter.hh>
73#endif
74
75#ifdef USE_OPENMP
76#endif
77
78#ifdef WIN32
79 #include <Windows/windows-startup.hh>
80#endif
81
82#include <CommandLine/CommandLineParser.hh>
83
84
85/* ==========================================================
86 *
87 * Linux function printing a full stack trace to the console
88 *
89 * ==========================================================*/
90#ifndef NO_EXECINFO
91
92#if defined(__GLIBCXX__) || defined(__GLIBCPP__)
93// GCC: implement demangling using cxxabi
94#include <cxxabi.h>
95std::string demangle(const std::string& _symbol)
96{
97 int status;
98 char* demangled = abi::__cxa_demangle(_symbol.c_str(), nullptr, nullptr, &status);
99 if (demangled) {
100 std::string result{demangled};
101 free(demangled);
102 if (status == 0) {
103 return result;
104 }
105 else {
106 return _symbol;
107 }
108 }
109 else {
110 return _symbol;
111 }
112}
113#else
114// other compiler environment: no demangling
115std::string demangle(const std::string& _symbol)
116{
117 return _symbol;
118}
119#endif
120
121void backtrace()
122{
123 void *addresses[20];
124 char **strings;
125
126 int size = backtrace(addresses, 20);
127 strings = backtrace_symbols(addresses, size);
128 std::cerr << "Stack frames: " << size << std::endl;
129 // line format:
130 // <path>(<mangled_name>+<offset>) [<address>]
131 std::regex line_format{R"(^\s*(.+)\‍((([^()]+)?\+(0x[0-9a-f]+))?\)\s+\[(0x[0-9a-f]+)\]\s*$)"};
132 for(int i = 0; i < size; i++) {
133 std::string line{strings[i]};
134 std::smatch match;
135 std::regex_match(line, match, line_format);
136 if (!match.empty()) {
137 auto file_name = match[1].str();
138 auto symbol = demangle(match[3].str());
139 auto offset = match[4].str();
140 auto address = match[5].str();
141 std::cerr << i << ":";
142 if (!file_name.empty()) std::cerr << " " << file_name << " ::";
143 if (!symbol.empty()) std::cerr << " " << symbol;
144 if (!offset.empty()) std::cerr << " (+" << offset << ")";
145 if (!address.empty()) std::cerr << " [" << address << "]";
146 std::cerr << std::endl;
147 }
148 }
149 free(strings);
150}
151#endif
152
153/* ==========================================================
154 *
155 * General segfault handler. This function is called if OpenFlipper
156 * crashes
157 *
158 * ==========================================================*/
159void segfaultHandling (int) {
160
161 // prevent infinite recursion if segfaultHandling() causes another segfault
162 std::signal(SIGSEGV, SIG_DFL);
163
164
165 std::cerr << "\n" << std::endl;
166 std::cerr << "\n" << std::endl;
167 std::cerr << "\33[31m" << "=====================================================" << std::endl;
168 std::cerr << "\33[31m" << "OpenFlipper or one of its plugins caused a Segfault." << std::endl;
169 std::cerr << "\33[31m" << "This should not happen,... Sorry :-(" << std::endl;
170 std::cerr << "\33[31m" << "=====================================================" << std::endl;
171 std::cerr << "\n" << std::endl;
172
173 // Linux Handler
174#ifndef NO_EXECINFO
175 std::cerr << "\33[0m" << "Trying a backtrace to show what happened last: " << std::endl;
176 backtrace();
177
178 std::cerr << "\n" << std::endl;
179 std::cerr << "Backtrace completed, trying to abort now ..." << std::endl;
180#endif
181
182 // Windows handler via StackWalker
183#ifdef WIN32
185 sw.ShowCallstack();
186#endif
187
188
189 std::cerr << "Trying to get additional information (This might fail if the memory is corrupted)." << std::endl;
190
191 if (OpenFlipper::Options::gui()) {
192 for ( unsigned int i = 0 ; i < 4 ; ++i) {
193 std::cerr << "DrawMode Viewer "<< i << " " << PluginFunctions::drawMode(i).description() << std::endl;
194 }
195 }
196
197 std::abort();
198}
199
200
201// Detector for OpenGL
202#include "OpenGL/OpenGLDetection.hh"
203
204int main(int argc, char **argv)
205{
206#ifdef _WIN32
207 // This make crashes visible - without them, starting the
208 // application from cmd.exe or powershell can surprisingly hide
209 // any signs of a an application crash!
210 SetErrorMode(0); // 0: Use the system default, which is to display all error dialog boxes.
211#endif
212
213
214 // Remove -psn_0_xxxxx argument which is automatically
215 // attached by MacOSX
216 for (int i = 0; i < argc; i++) {
217 if(strlen(argv[i]) > 4) {
218 if( ( (argv[i])[0] == '-' ) &&
219 ( (argv[i])[1] == 'p' ) &&
220 ( (argv[i])[2] == 's' ) &&
221 ( (argv[i])[3] == 'n' ) ) {
222 argc--;
223 argv[i] = (char *)"";
224 }
225 }
226 }
227
228 OpenFlipper::Options::argc(&argc);
229 OpenFlipper::Options::argv(&argv);
230
231 // Set organization and application names
232 QCoreApplication::setOrganizationName("VCI");
233 QCoreApplication::setApplicationName(TOSTRING(PRODUCT_STRING));
234 QCoreApplication::setApplicationVersion(OpenFlipper::Options::coreVersion());
235
236 // initialize a core application to check for commandline parameters
237 QCoreApplication* coreApp = new QCoreApplication(argc, argv);
238
239 OpenFlipper::Options::initializeSettings();
240
241 QCommandLineParser parser;
242 QString errorMessage;
243
244 // parse command line options
245 switch (parseCommandLine(parser, &errorMessage)) {
246 case CommandLineOk:
247 break;
248 case CommandLineError:
249 fputs(qPrintable(errorMessage), stderr);
250 fputs("\n\n", stderr);
251 fputs(qPrintable(parser.helpText()), stderr);
252 return 1;
253 case CommandLineVersionRequested:
254 printf("%s %s\n", qPrintable(QCoreApplication::applicationName()),
255 qPrintable(QCoreApplication::applicationVersion()));
256 return 0;
257 case CommandLineHelpRequested:
258 parser.showHelp();
259 Q_UNREACHABLE();
260 }
261
262 // only one application is allowed so delete the core application
263 // once cmdline parsing is done
264 delete coreApp;
265
266
267
268#ifdef WIN32
269 //attach a console if necessary
270 attachConsole();
271#endif
272
273#ifndef NO_CATCH_SIGSEGV
274 // Set a handler for segfaults
275 std::signal(SIGSEGV, segfaultHandling);
276#endif
277
278 OpenFlipper::Options::windowTitle(TOSTRING(PRODUCT_STRING)" v" + OpenFlipper::Options::coreVersion());
279
280 if ( !OpenFlipper::Options::nogui() ) {
281
282 // OpenGL check
283 QApplication::setAttribute(Qt::AA_ShareOpenGLContexts);
284
285 // Try creating a valid OpenGL context
286 /******************************/
287
288 // Get a valid context format
289 QSurfaceFormat resultFormat = getContextFormat();
290
291 // Set temporary(!) OpenGL settings
292 OpenFlipper::Options::samples(resultFormat.samples(), true);
293 OpenFlipper::Options::glStereo(resultFormat.stereo(), true);
294 OpenFlipper::Options::glVersion(resultFormat.version(), true);
295 OpenFlipper::Options::coreProfile(resultFormat.profile() == QSurfaceFormat::CoreProfile, true);
296
297 // Create the actual context
298 QSurfaceFormat::setDefaultFormat(resultFormat);
299 QApplication app(argc, argv);
300 QOffscreenSurface *surface = new QOffscreenSurface();
301 surface->create();
302
303 // Make the globally shared OpenGLContext current
304 QOpenGLContext::globalShareContext()->makeCurrent(surface);
305 /******************************/
306
307
308 // Check whether there is OpenGL support. If not, return.
309#if QT_VERSION_MAJOR < 6
310 if ( !QGLFormat::hasOpenGL() ) {
311#else
312 if ( QOpenGLContext::openGLModuleType() != QOpenGLContext::LibGL ) {
313#endif
314 std::cerr << "This system has no OpenGL support.\n";
315 return -1;
316 }
317
318 // create core ( this also reads the ini files )
319 Core * w = new Core( );
320#ifdef PYTHON_ENABLED
321 setCorePointer(w);
322#endif
323
324 QString tLang = OpenFlipperSettings().value("Core/Language/Translation","en_US").toString();
325
326 if (tLang == "locale")
327 tLang = QLocale::system().name();
328
329 // Install translator for qt internals
330 QTranslator qtTranslator;
331 #if QT_VERSION_MAJOR < 6
332 qtTranslator.load("qt_" + tLang, QLibraryInfo::location(QLibraryInfo::TranslationsPath));
333 #else
334 if ( ! qtTranslator.load("qt_" + tLang, QLibraryInfo::path(QLibraryInfo::TranslationsPath)) ) {
335 std::cerr << "Failed to load translation files!" << std::endl;
336 }
337 #endif
338
339 app.installTranslator(&qtTranslator);
340
341 // install translator for Core Application
342 QString translationDir = OpenFlipper::Options::translationsDirStr() + QDir::separator();
343 QDir dir(translationDir);
344 dir.setFilter(QDir::Files);
345
346 QFileInfoList list = dir.entryInfoList();
347
348 for (int i = 0; i < list.size(); ++i) {
349 QFileInfo fileInfo = list.at(i);
350
351 if ( fileInfo.baseName().contains(tLang) ){
352 QTranslator* myAppTranslator = new QTranslator();
353
354 if ( myAppTranslator->load( fileInfo.filePath() ) )
355 {
356 app.installTranslator(myAppTranslator);
357 } else
358 {
359 delete myAppTranslator;
360 }
361 }
362 }
363
364 #ifndef __APPLE__
365 initGlew();
366 #endif
367
368 // After setting all Options from command line, build the real gui
369 w->init();
370
371 const QStringList positionalArguments = parser.positionalArguments();
372
373 for ( auto file: positionalArguments ) {
374 w->commandLineOpen(file, openPolyMeshes);
375 }
376
377 return app.exec();
378
379 } else {
380
381 QCoreApplication app(argc,argv);
382
383 // create widget ( this also reads the ini files )
384 Core * w = new Core( );
385
386
387#ifdef PYTHON_ENABLED
388 setCorePointer(w);
389#endif
390
391 // After setting all Options from command line, build the real gui
392 w->init();
393
394 const QStringList positionalArguments = parser.positionalArguments();
395
396 for ( auto file: positionalArguments ) {
397 w->commandLineOpen(file, openPolyMeshes);
398 }
399
400 return app.exec();
401 }
402
403 return 0;
404}
#define TOSTRING(x)
QSettings object containing all program settings of OpenFlipper.
Definition Core.hh:133
void commandLineOpen(const QString &_filename, bool _asPolyMesh)
Load an object from the commandline on application start.
void init()
Second initialization stage.
Definition Core.cc:192
QVariant value(const QString &key, const QVariant &defaultValue=QVariant()) const
ACG::SceneGraph::DrawModes::DrawMode drawMode(int _viewer)
Get the current draw Mode of a Viewer.