Commit 09bc3a04 authored by NICLAUSSE Nicolas's avatar NICLAUSSE Nicolas

Merge branch 'release/1.7.0'

parents fd9a9ca9 c513e404
# ChangeLog
## version 1.7.0 - 2019-01-24
- add clear method in factory
- add option to replace plugin in factory
- add threading options to pythonInterpreter
- add option to redirect output in pythonInterpreter and use a specific settings file
## version 1.6.7 - 2018-11-23
- Swig: Add typecheck for QStringList
## version 1.6.6 - 2018-11-22
......
......@@ -23,8 +23,8 @@ project(dtk)
## ###################################################################
set(dtk_VERSION_MAJOR 1)
set(dtk_VERSION_MINOR 6)
set(dtk_VERSION_PATCH 7)
set(dtk_VERSION_MINOR 7)
set(dtk_VERSION_PATCH 0)
set(dtk_VERSION
${dtk_VERSION_MAJOR}.${dtk_VERSION_MINOR}.${dtk_VERSION_PATCH})
......
......@@ -28,7 +28,7 @@ int main(int argc, char **argv)
dtkDistributedGuiApplication *application = dtkDistributedGuiApplication::create(argc, argv);
application->setApplicationName("dtkComposerEvaluator");
application->setApplicationVersion("1.6.3");
application->setApplicationVersion("1.7.0");
application->setOrganizationName("inria");
application->setOrganizationDomain("fr");
bool no_gui = application->noGui();
......
......@@ -23,7 +23,7 @@ int main(int argc, char **argv)
{
dtkCoreApplication *application = dtkCoreApplication::create(argc, argv);
application->setApplicationName("dtkDistributedServer");
application->setApplicationVersion("1.6.3");
application->setApplicationVersion("1.7.0");
application->setOrganizationName("inria");
application->setOrganizationDomain("fr");
......
......@@ -15,7 +15,7 @@ public:
// typedef TYPE *(*creator) ();
public:
void recordPlugin(const QString& key, dtkCorePluginBase *plugin);
void recordPlugin(const QString& key, dtkCorePluginBase *plugin, bool force = false);
public:
TYPE *create(const QString& key) const /Factory/ ;
......
......@@ -55,9 +55,12 @@ public:
public:
void record(const QString& key, creator func);
void recordPlugin(const QString& key, dtkCorePluginBase *plugin);
void recordPlugin(const QString& key, dtkCorePluginBase *plugin, bool force = false);
void record(const QString& key, widget_creator func);
public:
void clear(void);
public:
T *create(const QString& key) const;
......
......@@ -48,11 +48,25 @@ template <typename T> inline void dtkCorePluginFactory<T>::record(const QString&
this->creators.insert(key, func);
}
template <typename T> inline void dtkCorePluginFactory<T>::recordPlugin(const QString& key, dtkCorePluginBase *plugin)
template <typename T> inline void dtkCorePluginFactory<T>::clear(void)
{
this->creators.clear();
for (QString key: this->creators_plugins.keys()) {
delete this->creators_plugins[key];
}
this->creators_plugins.clear();
}
template <typename T> inline void dtkCorePluginFactory<T>::recordPlugin(const QString& key, dtkCorePluginBase *plugin, bool force)
{
if (this->creators_plugins.contains(key)) {
qDebug() << Q_FUNC_INFO << "Factory already contains key" << key << ". Nothing is done";
return;
if (!force) {
qDebug() << Q_FUNC_INFO << "Factory already contains key" << key << ". Nothing is done";
return;
} else {
qDebug() << Q_FUNC_INFO << "Factory already contains key" << key << ". replace old plugin";
delete this->creators_plugins[key];
}
}
this->creators_plugins.insert(key, plugin);
......
......@@ -48,7 +48,7 @@ public:
public slots:
virtual QString interpret(const QString& command, int *stat) = 0;
virtual void init(void) {} ;
virtual void init(bool redirect_io = false, const QString & settings_file = QString("dtk-script")) {} ;
private:
dtkScriptInterpreterPrivate *d;
......
......@@ -34,7 +34,11 @@ static const QString dtkScriptInterpreterPythonRedirector_declare =
" def __init__(self):\n"
" self.data = ''\n"
" def write(self, stuff):\n"
" self.data+= stuff\n";
" self.data+= stuff\n"
" def flush(self):\n"
" pass\n"
" def reset(self):\n"
" self.data = ''\n";
static const QString dtkScriptInterpreterPythonRedirector_define =
"redirector = Redirector()\n"
......@@ -49,8 +53,19 @@ class dtkScriptInterpreterPythonPrivate
{
public:
QString buffer;
bool redirect_io = false;
public:
PyThreadState *thread_state = nullptr;
long thread_with_gil = -1;
PyGILState_STATE gilState;
public:
PyObject *module = nullptr;
};
// /////////////////////////////////////////////////////////////////
//
// /////////////////////////////////////////////////////////////////
......@@ -68,7 +83,7 @@ dtkScriptInterpreterPython *dtkScriptInterpreterPython::s_instance = nullptr;
dtkScriptInterpreterPython::dtkScriptInterpreterPython(void) : dtkScriptInterpreter(), d(new dtkScriptInterpreterPythonPrivate)
{
Py_Initialize();
}
dtkScriptInterpreterPython::~dtkScriptInterpreterPython(void)
......@@ -77,11 +92,15 @@ dtkScriptInterpreterPython::~dtkScriptInterpreterPython(void)
d = nullptr;
}
void dtkScriptInterpreterPython::init(void)
void dtkScriptInterpreterPython::init(bool redirect_io, const QString& settings_file)
{
Py_Initialize();
d->redirect_io = redirect_io;
if (redirect_io) {
PyRun_SimpleString(dtkScriptInterpreterPythonRedirector_declare.toUtf8().constData());
}
QSettings settings(QSettings::IniFormat, QSettings::UserScope, "inria", "dtk-script");
QSettings settings(QSettings::IniFormat, QSettings::UserScope, "inria", settings_file);
settings.beginGroup("modules");
QString paths = settings.value("path").toString();
settings.endGroup();
......@@ -100,7 +119,42 @@ void dtkScriptInterpreterPython::init(void)
if (!init.isEmpty()) {
PyRun_SimpleString(qPrintable(QString("execfile('%1')").arg(init)));
} else {
dtkWarn() << Q_FUNC_INFO << "No init function";
dtkInfo() << Q_FUNC_INFO << "No init function";
}
if (redirect_io) {
PyRun_SimpleString(dtkScriptInterpreterPythonRedirector_define.toUtf8().constData());
}
}
void dtkScriptInterpreterPython::allowThreads(void)
{
//init python threads
if(!PyEval_ThreadsInitialized()) {
qDebug() << "init threads";
PyEval_InitThreads(); // in 3.7 not needed anymore
}
d->thread_state = PyEval_SaveThread();
}
void dtkScriptInterpreterPython::endAllowThreads(void)
{
if(d->thread_state)
PyEval_RestoreThread(d->thread_state);
d->thread_state = nullptr;
}
void dtkScriptInterpreterPython::childAcquireLock(void)
{
d->thread_with_gil = long(QThread::currentThreadId());
d->gilState = PyGILState_Ensure();
}
void dtkScriptInterpreterPython::childReleaseLock(void)
{
long current_thread = long(QThread::currentThreadId());
if(current_thread == d->thread_with_gil) {
PyGILState_Release(d->gilState);
d->thread_with_gil = -1;
}
}
......@@ -141,16 +195,32 @@ QString dtkScriptInterpreterPython::interpret(const QString& command, int *stat)
return QString();
}
PyObject *module = PyImport_AddModule("__main__");
if (!d->module)
d->module = PyImport_AddModule("__main__");
switch (PyRun_SimpleString(qPrintable(statement))) {
switch(PyRun_SimpleString(qPrintable(statement))) {
case 0: *stat = Status_Ok; break;
case -1: *stat = Status_Error; break;
default: break;
}
PyErr_Print();
if (d->redirect_io) {
PyObject *redtor = PyObject_GetAttrString(d->module, "redirector");
if (redtor) {
PyObject *lresult = PyObject_GetAttrString(redtor, "data");
char *method = (char *)"reset";
PyObject_CallMethod(redtor, method, nullptr);
QString s = QString(PyString_AsString(lresult)).simplified();
Py_DECREF(redtor);
return s;
} else {
qDebug() << "no redirector found";
return QString();
}
}
PyErr_Print();
return QString();
}
......
......@@ -29,8 +29,16 @@ protected:
static dtkScriptInterpreterPython *s_instance;
public slots:
QString interpret(const QString& command, int *stat);
void init(void);
QString interpret(const QString& command, int *stat) override;
void init(bool redirect_io = false, const QString& settings_file = QString("dtk-script") ) override ;
public:
void allowThreads(void); // need to be called from main thread
void endAllowThreads(void); // need to be called from main thread
void childAcquireLock(void); // need to be called from child thread
void childReleaseLock(void); // need to be called from child thread
public:
void release(void);
private:
......
......@@ -74,6 +74,10 @@ void dtkCorePluginFactoryTestCase::testBasic(void)
dtkCorePluginFactoryTestConcept *concept = d->factory.create("dtkCorePluginFactoryTestConceptPlugin");
QVERIFY(concept);
QCOMPARE(QString("dtkCorePluginFactoryTestConceptPlugin"), concept->name());
d->factory.clear();
concept = d->factory.create("dtkCorePluginFactoryTestConceptPlugin");
QCOMPARE(nullptr, concept);
QCOMPARE(0, d->factory.keys().count());
}
void dtkCorePluginFactoryTestCase::cleanup(void)
......
......@@ -134,6 +134,10 @@ namespace Namespace {
$1 = PyInt_AsLong($input);
}
%typemap(in) const qlonglong& {
$1 = PyInt_AsLong($input);
}
%typemap(directorout) qlonglong {
PyObject *o = static_cast<PyObject *>($1);
if (PyInt_Check(o)) {
......@@ -148,6 +152,10 @@ namespace Namespace {
%typemap(typecheck) const qlonglong& = long long;
%typemap(typecheck) QString = char *;
%typemap(typecheck) const QString& = char *;
%typemap(typecheck) QString = const char *;
%typemap(typecheck) const QString& = const char *;
%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, noblock=1) QStringList {
$1 = PyList_Check($input) ? 1 : 0;
}
......@@ -195,9 +203,8 @@ namespace Namespace {
%typemap(in) QStringList {
if (PyList_Check($input)) {
int i = 0;
int end = PyList_Size($input);
for(i;i!=end; ++i) {
for(int i = 0; i!=end; ++i) {
$1 << QString(PyString_AsString(PyList_GET_ITEM($input, i)));
}
} else {
......@@ -207,10 +214,9 @@ namespace Namespace {
%typemap(in) const QStringList& {
if (PyList_Check($input)) {
int i = 0;
int end = PyList_Size($input);
$1 = new QStringList;
for(i;i!=end; ++i) {
for(int i = 0 ;i!=end; ++i) {
char *t = PyString_AsString(PyList_GET_ITEM($input, i));
(*$1) << QString(t);
}
......@@ -228,9 +234,8 @@ namespace Namespace {
%typemap(directorout) QStringList {
PyObject *list = static_cast<PyObject *>($1);
if (PyList_Check(list)) {
int i = 0;
int end = PyList_Size(list);
for(i;i<end; ++i) {
for(int i = 0; i<end; ++i) {
char *t = PyString_AsString(PyList_GET_ITEM(list, i));
$result << QString(t);
}
......@@ -243,9 +248,8 @@ namespace Namespace {
%typemap(in) QList<long> {
if (PyList_Check($input)) {
int i = 0;
int end = PyList_Size($input);
for(i;i!=end; ++i) {
for(int i = 0; i!=end; ++i) {
$1 << PyInt_AsLong(PyList_GET_ITEM($input, i));
}
} else {
......@@ -255,10 +259,9 @@ namespace Namespace {
%typemap(in) const QList<long>& {
if (PyList_Check($input)) {
int i = 0;
int end = PyList_Size($input);
$1 = new QList<long>;
for(i;i!=end; ++i) {
for(int i = 0; i!=end; ++i) {
($1)->append(PyInt_AsLong(PyList_GET_ITEM($input, i)));
}
} else {
......@@ -275,9 +278,8 @@ namespace Namespace {
%typemap(directorout) QList<long> {
PyObject *list = static_cast<PyObject *>($1);
if (PyList_Check(list)) {
int i = 0;
int end = PyList_Size(list);
for(i;i<end; ++i) {
for(int i = 0; i<end; ++i) {
PyObject *o = PyList_GET_ITEM(list, i);
$result << PyInt_AsLong(o);
}
......@@ -290,9 +292,8 @@ namespace Namespace {
%typemap(in) QList<double> {
if (PyList_Check($input)) {
int i = 0;
int end = PyList_Size($input);
for(i;i!=end; ++i) {
for(int i = 0; i!=end; ++i) {
$1 << PyFloat_AsDouble(PyList_GET_ITEM($input, i));
}
} else {
......@@ -302,10 +303,9 @@ namespace Namespace {
%typemap(in) const QList<double>& {
if (PyList_Check($input)) {
int i = 0;
int end = PyList_Size($input);
$1 = new QList<double>;
for(i;i!=end; ++i) {
for(int i = 0; i!=end; ++i) {
($1)->append(PyFloat_AsDouble(PyList_GET_ITEM($input, i)));
}
} else {
......@@ -322,9 +322,8 @@ namespace Namespace {
%typemap(directorout) QList<double> {
PyObject *list = static_cast<PyObject *>($1);
if (PyList_Check(list)) {
int i = 0;
int end = PyList_Size(list);
for(i;i<end; ++i) {
for(int i = 0; i<end; ++i) {
PyObject *o = PyList_GET_ITEM(list, i);
$result << PyFloat_AsDouble(o);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment