mirror of
https://github.com/GoldenCheetah/GoldenCheetah.git
synced 2026-02-14 00:28:42 +00:00
R Console exceptions
.. don't crash when cannot initialise (e.g. when RInside not available or R is not installed) .. handle messaging via signals to trap 'late' messages from the R Runtime
This commit is contained in:
@@ -33,6 +33,7 @@ RConsole::RConsole(Context *context, QWidget *parent)
|
||||
putData(GCColor::invertColor(GColor(CPLOTBACKGROUND)), "\n> ");
|
||||
|
||||
connect(context, SIGNAL(configChanged(qint32)), this, SLOT(configChanged(qint32)));
|
||||
connect(context, SIGNAL(rMessage(QString)), this, SLOT(rMessage(QString)));
|
||||
|
||||
// history position
|
||||
hpos=0;
|
||||
@@ -52,6 +53,11 @@ RConsole::configChanged(qint32)
|
||||
setStyleSheet(TabView::ourStyleSheet());
|
||||
}
|
||||
|
||||
void
|
||||
RConsole::rMessage(QString x)
|
||||
{
|
||||
putData(GColor(CPLOTMARKER), x);
|
||||
}
|
||||
|
||||
void RConsole::putData(QColor color, QString string)
|
||||
{
|
||||
@@ -133,7 +139,7 @@ void RConsole::keyPressEvent(QKeyEvent *e)
|
||||
SEXP ret = rtool->R->parseEval(line.toStdString());
|
||||
|
||||
// if this isn't an assignment then print the result
|
||||
if(!line.contains("<-")) Rcpp::print(ret);
|
||||
if(!Rf_isNull(ret) && !line.contains("<-")) Rcpp::print(ret);
|
||||
|
||||
QStringList &response = rtool->callbacks->getConsoleOutput();
|
||||
putData(GColor(CPLOTMARKER), response.join(""));
|
||||
@@ -216,20 +222,24 @@ RChart::RChart(Context *context) : GcChartWindow(context)
|
||||
mainLayout->setContentsMargins(2,0,2,2);
|
||||
setChartLayout(mainLayout);
|
||||
|
||||
splitter = new QSplitter(Qt::Horizontal, this);
|
||||
splitter->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding));
|
||||
splitter->setHandleWidth(1);
|
||||
mainLayout->addWidget(splitter);
|
||||
// if we failed to startup the RInside properly
|
||||
// then disable the RConsole altogether.
|
||||
if (rtool->R) {
|
||||
splitter = new QSplitter(Qt::Horizontal, this);
|
||||
splitter->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding));
|
||||
splitter->setHandleWidth(1);
|
||||
mainLayout->addWidget(splitter);
|
||||
|
||||
console = new RConsole(context, this);
|
||||
splitter->addWidget(console);
|
||||
QWidget *surface = new QSvgWidget(this);
|
||||
surface->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding));
|
||||
splitter->addWidget(surface);
|
||||
console = new RConsole(context, this);
|
||||
splitter->addWidget(console);
|
||||
QWidget *surface = new QSvgWidget(this);
|
||||
surface->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding));
|
||||
splitter->addWidget(surface);
|
||||
|
||||
QPalette p = palette();
|
||||
p.setColor(QPalette::Base, GColor(CPLOTBACKGROUND));
|
||||
p.setColor(QPalette::Text, GCColor::invertColor(GColor(CPLOTBACKGROUND)));
|
||||
surface->setPalette(p);
|
||||
QPalette p = palette();
|
||||
p.setColor(QPalette::Base, GColor(CPLOTBACKGROUND));
|
||||
p.setColor(QPalette::Text, GCColor::invertColor(GColor(CPLOTBACKGROUND)));
|
||||
surface->setPalette(p);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -33,39 +33,6 @@
|
||||
#include "Context.h"
|
||||
#include "Athlete.h"
|
||||
|
||||
class RInside;
|
||||
class RCallbacks;
|
||||
class QString;
|
||||
|
||||
extern RInside *gc_RInside;
|
||||
extern RCallbacks *gc_RCallbacks;
|
||||
extern QString gc_RVersion;
|
||||
extern Context *gc_RContext;
|
||||
|
||||
// global singleton catches output from R interpreter
|
||||
// first come first served on output
|
||||
class RCallbacks : public Callbacks {
|
||||
public:
|
||||
// see inst/includes/Callbacks.h for a list of all overrideable methods
|
||||
virtual void WriteConsole(const std::string& line, int type) {
|
||||
//qDebug()<<"Console>>" <<type<< QString::fromStdString(line);
|
||||
strings << QString::fromStdString(line);
|
||||
};
|
||||
|
||||
virtual void ShowMessage(const char* message) {
|
||||
//qDebug()<<"M:" << QString(message);
|
||||
strings << QString(message);
|
||||
}
|
||||
|
||||
virtual bool has_ShowMessage() { return true; }
|
||||
virtual bool has_WriteConsole() { return true; }
|
||||
|
||||
QStringList &getConsoleOutput() {
|
||||
return strings;
|
||||
}
|
||||
private:
|
||||
QStringList strings;
|
||||
};
|
||||
|
||||
// a console widget to type commands and display response
|
||||
class RConsole : public QTextEdit {
|
||||
@@ -77,6 +44,7 @@ signals:
|
||||
|
||||
public slots:
|
||||
void configChanged(qint32);
|
||||
void rMessage(QString);
|
||||
|
||||
public:
|
||||
explicit RConsole(Context *context, QWidget *parent = 0);
|
||||
|
||||
@@ -31,39 +31,58 @@
|
||||
RTool::RTool(int argc, char**argv)
|
||||
{
|
||||
// setup the R runtime elements
|
||||
R = new RInside(argc,argv);
|
||||
callbacks = new RCallbacks;
|
||||
R->set_callbacks(callbacks);
|
||||
bool failed = false;
|
||||
try {
|
||||
|
||||
// lets get the version early for the about dialog
|
||||
R->parseEvalNT("print(R.version.string)");
|
||||
QStringList &strings = callbacks->getConsoleOutput();
|
||||
if (strings.count() == 3) {
|
||||
QRegExp exp("^.*([0-9]+\\.[0-9]+\\.[0-9]+).*$");
|
||||
if (exp.exactMatch(strings[1])) version = exp.cap(1);
|
||||
else version = strings[1];
|
||||
R = new RInside(argc,argv);
|
||||
callbacks = new RCallbacks;
|
||||
R->set_callbacks(callbacks);
|
||||
|
||||
// lets get the version early for the about dialog
|
||||
R->parseEvalNT("print(R.version.string)");
|
||||
QStringList &strings = callbacks->getConsoleOutput();
|
||||
if (strings.count() == 3) {
|
||||
QRegExp exp("^.*([0-9]+\\.[0-9]+\\.[0-9]+).*$");
|
||||
if (exp.exactMatch(strings[1])) version = exp.cap(1);
|
||||
else version = strings[1];
|
||||
}
|
||||
strings.clear();
|
||||
|
||||
// set the "GC" object and methods
|
||||
context = NULL;
|
||||
(*R)["GC.version"] = VERSION_STRING;
|
||||
(*R)["GC.build"] = VERSION_LATEST;
|
||||
|
||||
// Access into the GC data
|
||||
(*R)["GC.activities"] = Rcpp::InternalFunction(RTool::activities);
|
||||
(*R)["GC.activity"] = Rcpp::InternalFunction(RTool::activity);
|
||||
|
||||
// TBD
|
||||
// GC.metrics - list of activities and their metrics
|
||||
// GC.activity - single activity and its data series
|
||||
// GC.seasons - configured seasons
|
||||
// GC.season - currently selected season
|
||||
// GC.config - configuration (zones, units etc)
|
||||
|
||||
// the following are already set in RChart on a per call basis
|
||||
// "GC.athlete" "GC.athlete.home"
|
||||
|
||||
} catch(std::exception& ex) {
|
||||
|
||||
qDebug()<<"RInside error:" << ex.what();
|
||||
failed = true;
|
||||
|
||||
} catch(...) {
|
||||
|
||||
failed = true;
|
||||
}
|
||||
strings.clear();
|
||||
|
||||
// set the "GC" object and methods
|
||||
context = NULL;
|
||||
(*R)["GC.version"] = VERSION_STRING;
|
||||
(*R)["GC.build"] = VERSION_LATEST;
|
||||
|
||||
// Access into the GC data
|
||||
(*R)["GC.activities"] = Rcpp::InternalFunction(RTool::activities);
|
||||
(*R)["GC.activity"] = Rcpp::InternalFunction(RTool::activity);
|
||||
|
||||
// TBD
|
||||
// GC.metrics - list of activities and their metrics
|
||||
// GC.activity - single activity and its data series
|
||||
// GC.seasons - configured seasons
|
||||
// GC.season - currently selected season
|
||||
// GC.config - configuration (zones, units etc)
|
||||
|
||||
// the following are already set in RChart on a per call basis
|
||||
// "GC.athlete" "GC.athlete.home"
|
||||
|
||||
// ack, disable R runtime
|
||||
if (failed) {
|
||||
qDebug() << "RInside/Rcpp failed to start, RConsole disabled.";
|
||||
version = "none";
|
||||
R = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
Rcpp::DatetimeVector
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
#ifndef _GC_RTool_h
|
||||
|
||||
class RCallbacks;
|
||||
class RTool {
|
||||
|
||||
public:
|
||||
@@ -35,5 +36,34 @@ class RTool {
|
||||
static Rcpp::DatetimeVector activities();
|
||||
};
|
||||
|
||||
// there is a global instance created in main
|
||||
extern RTool *rtool;
|
||||
|
||||
// global singleton catches output from R interpreter
|
||||
// first come first served on output
|
||||
class RCallbacks : public Callbacks {
|
||||
|
||||
public:
|
||||
// see inst/includes/Callbacks.h for a list of all overrideable methods
|
||||
virtual void WriteConsole(const std::string& line, int type) {
|
||||
//qDebug()<<"Console>>" <<type<< QString::fromStdString(line);
|
||||
if (rtool && rtool->context) rtool->context->notifyRMessage(QString::fromStdString(line));
|
||||
else strings << QString::fromStdString(line);
|
||||
};
|
||||
|
||||
//virtual void ShowMessage(const char* message) {
|
||||
//qDebug()<<"M:" << QString(message);
|
||||
//strings << QString(message);
|
||||
//}
|
||||
|
||||
//virtual bool has_ShowMessage() { return true; }
|
||||
virtual bool has_WriteConsole() { return true; }
|
||||
|
||||
QStringList &getConsoleOutput() {
|
||||
return strings;
|
||||
}
|
||||
private:
|
||||
QStringList strings;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -190,6 +190,7 @@ class Context : public QObject
|
||||
void notifyRefreshEnd() { emit refreshEnd(); }
|
||||
void notifyRefreshUpdate(QDate date) { emit refreshUpdate(date); }
|
||||
|
||||
void notifyRMessage(QString x) { emit rMessage(x); }
|
||||
void notifyCompareIntervals(bool state);
|
||||
void notifyCompareIntervalsChanged();
|
||||
|
||||
@@ -261,6 +262,9 @@ class Context : public QObject
|
||||
void pause();
|
||||
void stop();
|
||||
|
||||
// R messages
|
||||
void rMessage(QString);
|
||||
|
||||
// comparing things
|
||||
void compareIntervalsStateChanged(bool);
|
||||
void compareIntervalsChanged();
|
||||
|
||||
Reference in New Issue
Block a user