mirror of https://github.com/CGAL/cgal
fixup! Better exception handling (with Qt Script)
This commit is contained in:
parent
ed2eae8879
commit
54dbab9d3c
|
|
@ -433,17 +433,25 @@ void MainWindow::evaluate_script(QString script,
|
||||||
const bool quiet) {
|
const bool quiet) {
|
||||||
QScriptValue value = script_engine->evaluate(script, filename);
|
QScriptValue value = script_engine->evaluate(script, filename);
|
||||||
if(script_engine->hasUncaughtException()) {
|
if(script_engine->hasUncaughtException()) {
|
||||||
|
QScriptValue js_exception = script_engine->uncaughtException();
|
||||||
|
QScriptValue js_bt =js_exception.property("backtrace");
|
||||||
|
QStringList bt = script_engine->uncaughtExceptionBacktrace();
|
||||||
|
if(js_bt.isValid()) {
|
||||||
|
QStringList other_bt;
|
||||||
|
qScriptValueToSequence(js_bt, other_bt);
|
||||||
|
if(!other_bt.isEmpty()) bt = other_bt;
|
||||||
|
}
|
||||||
if(!quiet) {
|
if(!quiet) {
|
||||||
QTextStream err(stderr);
|
QTextStream err(stderr);
|
||||||
err << "Qt Script exception:\n"
|
err << "Qt Script exception:\n"
|
||||||
<< script_engine->uncaughtException().toString()
|
<< js_exception.toString()
|
||||||
<< "\nBacktrace:\n";
|
<< "\nBacktrace:\n";
|
||||||
Q_FOREACH(QString line, script_engine->uncaughtExceptionBacktrace()) {
|
Q_FOREACH(QString line, bt) {
|
||||||
err << " " << line << "\n";
|
err << " " << line << "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw CGAL::Three::Script_exception
|
throw CGAL::Three::Script_exception
|
||||||
(script_engine->uncaughtException().toString().toStdString());
|
(script_engine->uncaughtException().toString(), bt);
|
||||||
}
|
}
|
||||||
else if(!quiet && !value.isNull() && !value.isUndefined()) {
|
else if(!quiet && !value.isNull() && !value.isUndefined()) {
|
||||||
QTextStream(stderr) << "Qt Script evaluated to \""
|
QTextStream(stderr) << "Qt Script evaluated to \""
|
||||||
|
|
@ -468,6 +476,10 @@ void MainWindow::enableScriptDebugger(bool b /* = true */)
|
||||||
if(b) {
|
if(b) {
|
||||||
debugger->action(QScriptEngineDebugger::InterruptAction)->trigger();
|
debugger->action(QScriptEngineDebugger::InterruptAction)->trigger();
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
std::cerr << "Detach the script debugger\n";
|
||||||
|
debugger->detach();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
# endif
|
# endif
|
||||||
|
|
@ -1389,6 +1401,13 @@ bool MainWindow::loadScript(QFileInfo info)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::throw_exception() {
|
||||||
|
wrap_a_call_to_cpp([]() {
|
||||||
|
throw std::runtime_error("Exception thrown in "
|
||||||
|
"MainWindow::throw_exception()");
|
||||||
|
}, this, __FILE__, __LINE__);
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::on_actionLoadScript_triggered()
|
void MainWindow::on_actionLoadScript_triggered()
|
||||||
{
|
{
|
||||||
#if defined(QT_SCRIPT_LIB)
|
#if defined(QT_SCRIPT_LIB)
|
||||||
|
|
|
||||||
|
|
@ -210,6 +210,8 @@ public Q_SLOTS:
|
||||||
*/
|
*/
|
||||||
void enableScriptDebugger(bool = true);
|
void enableScriptDebugger(bool = true);
|
||||||
|
|
||||||
|
/// This slot is used to test exception handling in Qt Scripts.
|
||||||
|
void throw_exception();
|
||||||
protected Q_SLOTS:
|
protected Q_SLOTS:
|
||||||
|
|
||||||
//!Gets the new selected item(s) from the sceneView and updates the scene
|
//!Gets the new selected item(s) from the sceneView and updates the scene
|
||||||
|
|
|
||||||
|
|
@ -139,13 +139,11 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
#include <CGAL/Three/Polyhedron_demo_plugin_interface.h>
|
#include <CGAL/Three/Polyhedron_demo_plugin_interface.h>
|
||||||
#include <CGAL/Three/exceptions.h>
|
|
||||||
|
|
||||||
using namespace CGAL::Three;
|
using namespace CGAL::Three;
|
||||||
class Polyhedron_demo_trivial_plugin :
|
class Polyhedron_demo_trivial_plugin :
|
||||||
public QObject,
|
public QObject,
|
||||||
public Polyhedron_demo_plugin_interface,
|
public Polyhedron_demo_plugin_interface
|
||||||
protected QScriptable
|
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_INTERFACES(CGAL::Three::Polyhedron_demo_plugin_interface)
|
Q_INTERFACES(CGAL::Three::Polyhedron_demo_plugin_interface)
|
||||||
|
|
@ -163,13 +161,6 @@ public:
|
||||||
return false;}
|
return false;}
|
||||||
public Q_SLOTS:
|
public Q_SLOTS:
|
||||||
|
|
||||||
/// This slot is used to test exception handling in Qt Scripts.
|
|
||||||
void throw_exception() {
|
|
||||||
wrap_a_call_to_cpp([]() {
|
|
||||||
throw std::runtime_error("Exception thrown in "
|
|
||||||
"Trivial_plugin::throw_exception()");
|
|
||||||
}, this, __FILE__, __LINE__);
|
|
||||||
}
|
|
||||||
void bbox();
|
void bbox();
|
||||||
void enableAction();
|
void enableAction();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -47,11 +47,12 @@ Polyhedron_demo::Polyhedron_demo(int& argc, char **argv,
|
||||||
QCommandLineOption no_try_catch("no-try-catch",
|
QCommandLineOption no_try_catch("no-try-catch",
|
||||||
tr("Do not catch uncaught exceptions."));
|
tr("Do not catch uncaught exceptions."));
|
||||||
parser.addOption(no_try_catch);
|
parser.addOption(no_try_catch);
|
||||||
#ifdef QT_SCRIPTTOOLS_LIB
|
|
||||||
QCommandLineOption debug_scripts("debug-scripts",
|
QCommandLineOption debug_scripts("debug-scripts",
|
||||||
tr("Use the scripts debugger."));
|
tr("Use the scripts debugger."));
|
||||||
parser.addOption(debug_scripts);
|
parser.addOption(debug_scripts);
|
||||||
#endif
|
QCommandLineOption no_debug_scripts("no-debug-scripts",
|
||||||
|
tr("Do not use the scripts debugger."));
|
||||||
|
parser.addOption(no_debug_scripts);
|
||||||
QCommandLineOption no_autostart("no-autostart",
|
QCommandLineOption no_autostart("no-autostart",
|
||||||
tr("Ignore the autostart.js file, if any."));
|
tr("Ignore the autostart.js file, if any."));
|
||||||
parser.addOption(no_autostart);
|
parser.addOption(no_autostart);
|
||||||
|
|
@ -74,7 +75,16 @@ Polyhedron_demo::Polyhedron_demo(int& argc, char **argv,
|
||||||
if(parser.isSet(debug_scripts)) {
|
if(parser.isSet(debug_scripts)) {
|
||||||
mainWindow.enableScriptDebugger();
|
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
|
#endif
|
||||||
|
|
||||||
mainWindow.loadScript(":/cgal/Polyhedron_3/javascript/lib.js");
|
mainWindow.loadScript(":/cgal/Polyhedron_3/javascript/lib.js");
|
||||||
QFileInfo autostart_js("autostart.js");
|
QFileInfo autostart_js("autostart.js");
|
||||||
if(!parser.isSet(no_autostart) && autostart_js.exists()) {
|
if(!parser.isSet(no_autostart) && autostart_js.exists()) {
|
||||||
|
|
|
||||||
|
|
@ -26,17 +26,23 @@
|
||||||
#include <QScriptable>
|
#include <QScriptable>
|
||||||
#include <QScriptContext>
|
#include <QScriptContext>
|
||||||
#include <boost/optional.hpp>
|
#include <boost/optional.hpp>
|
||||||
|
#include <QStringList>
|
||||||
|
|
||||||
namespace CGAL{
|
namespace CGAL{
|
||||||
namespace Three{
|
namespace Three{
|
||||||
|
|
||||||
struct Script_exception : public std::runtime_error {
|
class Script_exception : public std::runtime_error {
|
||||||
Script_exception(const std::string& what_arg)
|
QStringList bt;
|
||||||
: std::runtime_error(what_arg)
|
public:
|
||||||
{}
|
Script_exception(QString what_arg,
|
||||||
Script_exception(QString what_arg)
|
QStringList backtrace)
|
||||||
: std::runtime_error(what_arg.toStdString())
|
: std::runtime_error(what_arg.toStdString())
|
||||||
|
, bt(backtrace)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
QStringList backtrace() const {
|
||||||
|
return bt;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
|
@ -73,14 +79,41 @@ wrap_a_call_to_cpp(Callable f,
|
||||||
return f();
|
return f();
|
||||||
}
|
}
|
||||||
catch(const std::exception& e) {
|
catch(const std::exception& e) {
|
||||||
|
const Script_exception* se = dynamic_cast<const Script_exception*>(&e);
|
||||||
QScriptContext* context = qs->context();
|
QScriptContext* context = qs->context();
|
||||||
if(c == PARENT_CONTEXT) context = context->parentContext();
|
QStringList qt_bt = context->backtrace();
|
||||||
QString error = QObject::tr("Error");
|
if(se) qt_bt = se->backtrace();
|
||||||
if(file != 0) error += QObject::tr(" at file %1").arg(file);
|
std::cerr << "Backtrace:\n";
|
||||||
if(line != -1) error += QString(":%1").arg(line);
|
Q_FOREACH(QString s, qt_bt)
|
||||||
error += QString(":\n%1").arg(e.what());
|
{
|
||||||
|
std::cerr << " " << qPrintable(s) << std::endl;
|
||||||
|
}
|
||||||
|
context = context->parentContext();
|
||||||
|
if(c == PARENT_CONTEXT) {
|
||||||
|
std::cerr << "> parent";
|
||||||
|
context = context->parentContext();
|
||||||
|
} else {
|
||||||
|
std::cerr << "> current";
|
||||||
|
}
|
||||||
|
std::cerr << " context: "
|
||||||
|
<< qPrintable(context->toString()) << std::endl;
|
||||||
|
QString error;
|
||||||
|
if(se) {
|
||||||
|
error = se->what();
|
||||||
|
} else {
|
||||||
|
error = QObject::tr("Error");
|
||||||
|
QString context;
|
||||||
|
if(file != 0) context += QObject::tr(" at file %1").arg(file);
|
||||||
|
if(line != -1) context += QString(":%1").arg(line);
|
||||||
|
if(!context.isNull()) {
|
||||||
|
error += context;
|
||||||
|
qt_bt.push_front(QObject::tr("<cpp>") + context);
|
||||||
|
}
|
||||||
|
error += QString(": %1").arg(e.what());
|
||||||
|
}
|
||||||
QScriptValue v = context->throwError(error);
|
QScriptValue v = context->throwError(error);
|
||||||
v.setProperty("backtrace", context->backtrace().join(";"));
|
v.setProperty("backtrace",
|
||||||
|
qScriptValueFromSequence(context->engine(), qt_bt));
|
||||||
std::cerr << "result after throwError: "
|
std::cerr << "result after throwError: "
|
||||||
<< qPrintable(v.toString()) << std::endl;
|
<< qPrintable(v.toString()) << std::endl;
|
||||||
return Return_type();
|
return Return_type();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue