1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
|
#include "CGALlab.h"
#include "MainWindow.h"
#include <QMessageBox>
#include <CGAL/Qt/resources.h>
#include <stdexcept>
#include <QCommandLineParser>
#include <QCommandLineOption>
#include <QSurfaceFormat>
#include <QOpenGLContext>
#include <clocale>
struct CGAL_Lab_impl {
bool catch_exceptions;
QScopedPointer<MainWindow> mainWindow;
CGAL_Lab_impl() : catch_exceptions(true) {}
}; // end struct CGAL_Lab_impl
int& code_to_call_before_creation_of_QCoreApplication(int& i) {
QSurfaceFormat fmt;
fmt.setVersion(4, 3);
fmt.setRenderableType(QSurfaceFormat::OpenGL);
fmt.setProfile(QSurfaceFormat::CoreProfile);
fmt.setOption(QSurfaceFormat::DebugContext);
QSurfaceFormat::setDefaultFormat(fmt);
// for windows
QCoreApplication::setAttribute(Qt::AA_UseDesktopOpenGL);
return i;
}
CGAL_Lab::CGAL_Lab(int& argc, char **argv,
QString application_name,
QString main_window_title,
QStringList input_keywords)
: QApplication(code_to_call_before_creation_of_QCoreApplication(argc),
// This trick in the previous line ensure that code
// is called before the creation of the QApplication
// object.
argv)
, d_ptr_is_initialized(false)
, d_ptr(new CGAL_Lab_impl)
{
//We set the locale to avoid any trouble with VTK
std::setlocale(LC_ALL, "C");
d_ptr_is_initialized = true;
std::cerr.precision(17);
std::cout.precision(17);
std::clog.precision(17);
// Import resources from libCGAL (Qt6).
CGAL_QT_INIT_RESOURCES;
this->setOrganizationDomain("geometryfactory.com");
this->setOrganizationName("GeometryFactory");
this->setApplicationName(application_name);
QCommandLineParser parser;
parser.addHelpOption();
QCommandLineOption use_keyword("keyword",
tr("Only loads the plugins associated with the following keyword. Can be called multiple times."),
"keyword");
parser.addOption(use_keyword);
QCommandLineOption use_meta("use-meta",
tr("Use the [Meta] key to move frames, instead of [Tab]."));
parser.addOption(use_meta);
QCommandLineOption no_try_catch("no-try-catch",
tr("Do not catch uncaught exceptions."));
parser.addOption(no_try_catch);
QCommandLineOption debug_scripts("debug-scripts",
tr("Use the scripts debugger."));
parser.addOption(debug_scripts);
QCommandLineOption no_debug_scripts("no-debug-scripts",
tr("Do not use the scripts debugger."));
parser.addOption(no_debug_scripts);
QCommandLineOption no_autostart("no-autostart",
tr("Ignore the autostart.js file, if any."));
parser.addOption(no_autostart);
QCommandLineOption verbose("verbose",
tr("Print the paths explored by the application searching for plugins."));
parser.addOption(verbose);
QCommandLineOption old("old",
tr("Force OpenGL 2.1 context."));
parser.addOption(old);
parser.addPositionalArgument("files", tr("Files to open"), "[files...]");
parser.process(*this);
QStringList keywords = input_keywords;
QStringList parser_keywords = parser.values(use_keyword);
keywords.append(parser_keywords);
d_ptr->mainWindow.reset(new MainWindow(keywords, parser.isSet(verbose)));
MainWindow& mainWindow = *d_ptr->mainWindow;
mainWindow.setWindowTitle(main_window_title);
mainWindow.show();
// On Apple, the first time the application is launched, the menus are unclicable, and
// the only way you can fix it is to unfocus and re-focus the application.
// This is a hack that makes the application lose the focus after it is started, to force the user
// to re-focus it. (source: https://www.alecjacobson.com/weblog/?p=3910)
#ifdef __APPLE__
system("osascript -e 'tell application \"System Events\" "
"to keystroke tab using {command down, shift down}'");
#endif
if(parser.isSet(use_meta)) {
mainWindow.setAddKeyFrameKeyboardModifiers(::Qt::MetaModifier);
}
if(parser.isSet(no_try_catch)) {
this->do_not_catch_exceptions();
}
#ifdef QT_SCRIPTTOOLS_LIB
if(parser.isSet(debug_scripts)) {
mainWindow.enableScriptDebugger();
}
if(parser.isSet(no_debug_scripts)) {
mainWindow.enableScriptDebugger(false);
}
#else
if(parser.isSet(debug_scripts)) {
std::cerr << "Qt Script Tools have not been configured!";
abort();
}
#endif
mainWindow.loadScript(":/cgal/Lab/javascript/lib.js");
QFileInfo autostart_js("autostart.js");
if(!parser.isSet(no_autostart) && autostart_js.exists()) {
mainWindow.loadScript(autostart_js);
}
for(QString filename : parser.positionalArguments()) {
mainWindow.open(filename);
}
}
CGAL_Lab::~CGAL_Lab() {}
void CGAL_Lab::do_not_catch_exceptions() {
d_ptr->catch_exceptions = false;
setProperty("no-try-catch", true);
}
bool CGAL_Lab::notify(QObject* receiver, QEvent* event)
{
if(!d_ptr_is_initialized || !d_ptr->catch_exceptions)
return QApplication::notify(receiver, event);
else try {
return QApplication::notify(receiver, event);
} catch (std::exception &e) {
// find the mainwindow to spawn an error message
for (QWidget *widget : QApplication::topLevelWidgets()) {
if(MainWindow* mw = qobject_cast<MainWindow*>(widget)) {
QMessageBox::critical(mw,
tr("Unhandled exception"),
tr("<p>Unhandled exception:</p>\n"
"<pre>%1</pre>").arg(e.what()));
break;
}
}
QApplication::restoreOverrideCursor();
} catch (...) {
qFatal("Unknown exception encountered. Aborting.");
}
return false;
}
int CGAL_Lab::try_exec()
{
// A Qt Script may have closed the main window.
// The following loop launch app.exec() only if the main window is visible.
if(d_ptr->mainWindow->isVisible()) {
return this->exec();
}
return 0;
}
|