Skip to content

Commit

Permalink
Merged in actuator_status (pull request #21)
Browse files Browse the repository at this point in the history
Actuator status, AddInInterface cleanup
  • Loading branch information
magro11 authored and gegelle committed Mar 15, 2019
2 parents 8326a8b + 33baee2 commit 72a6efe
Show file tree
Hide file tree
Showing 17 changed files with 741 additions and 226 deletions.
7 changes: 7 additions & 0 deletions AddInManager/addInManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,13 @@ along with itom. If not, see <http://www.gnu.org/licenses/>.
#include <qpointer.h>
#include <qtimer.h>
#include <qtranslator.h>
#include <qlibrary.h>

#if QT_VERSION < 0x050000
#include <qpluginloader.h>
#else
#include <QtCore/qpluginloader.h>
#endif

// in the invokeMethod function parameters are passed with the Q_ARG macro, which works only with preregistered data types
// the registration of "new" data types is done in two steps. First they are declared with the Q_DECLARE_METATYPE macro
Expand Down
6 changes: 6 additions & 0 deletions AddInManager/addInManagerPrivate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ along with itom. If not, see <http://www.gnu.org/licenses/>.
#include "pluginModel.h"
#include "addInManager.h"

#if QT_VERSION < 0x050000
#include <qpluginloader.h>
#else
#include <QtCore/qpluginloader.h>
#endif

namespace ito
{

Expand Down
6 changes: 6 additions & 0 deletions Qitom/python/pythonItom.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@
#include <qdesktopwidget.h>
#include <qstringlist.h>

#if QT_VERSION < 0x050000
#include <qpluginloader.h>
#else
#include <QtCore/qpluginloader.h>
#endif

#include "opencv2/core/core_c.h"

QHash<size_t, QString> ito::PythonItom::m_gcTrackerList;
Expand Down
190 changes: 165 additions & 25 deletions Qitom/python/pythonPlugins.cpp

Large diffs are not rendered by default.

13 changes: 9 additions & 4 deletions Qitom/python/pythonPlugins.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,8 @@ class PythonPlugins
static PyObject *PyActuatorPlugin_showToolbox(PyActuatorPlugin *self);
static PyObject *PyActuatorPlugin_hideToolbox(PyActuatorPlugin *self);

static PyObject *PyActuatorPlugin_connect(PyActuatorPlugin *self, PyObject* args);
static PyObject *PyActuatorPlugin_disconnect(PyActuatorPlugin *self, PyObject* args);
static PyObject *PyActuatorPlugin_connect(PyActuatorPlugin *self, PyObject* args, PyObject* kwds);
static PyObject *PyActuatorPlugin_disconnect(PyActuatorPlugin *self, PyObject* args, PyObject* kwds);
static PyObject *PyActuatorPlugin_info(PyActuatorPlugin *self, PyObject* args);
static PyObject *PyActuatorPlugin_setInterrupt(PyActuatorPlugin *self);

Expand All @@ -111,8 +111,13 @@ class PythonPlugins
static PyObject *PyActuatorPlugin_setPosAbs(PyActuatorPlugin *self, PyObject *args);
static PyObject *PyActuatorPlugin_setPosRel(PyActuatorPlugin *self, PyObject *args);

static PyObject* PyActuatorPlugin_getCurrentStatus(PyActuatorPlugin *self, void *closure);
static PyObject* PyActuatorPlugin_getCurrentPositions(PyActuatorPlugin *self, void *closure);
static PyObject* PyActuatorPlugin_getTargetPositions(PyActuatorPlugin *self, void *closure);

static PyMemberDef PyActuatorPlugin_members[];
static PyMethodDef PyActuatorPlugin_methods[];
static PyGetSetDef PyActuatorPlugin_getseters[];
static PyTypeObject PyActuatorPluginType;
static PyModuleDef PyActuatorPluginModule;

Expand Down Expand Up @@ -153,8 +158,8 @@ class PythonPlugins
static PyObject *PyDataIOPlugin_getAutoGrabbing(PyDataIOPlugin *self, PyObject *args);
static PyObject *PyDataIOPlugin_setAutoGrabbingInterval(PyDataIOPlugin *self, PyObject *args);
static PyObject *PyDataIOPlugin_getAutoGrabbingInterval(PyDataIOPlugin *self);
static PyObject *PyDataIOPlugin_connect(PyDataIOPlugin *self, PyObject *args);
static PyObject *PyDataIOPlugin_disconnect(PyDataIOPlugin *self, PyObject *args);
static PyObject *PyDataIOPlugin_connect(PyDataIOPlugin *self, PyObject *args, PyObject* kwds);
static PyObject *PyDataIOPlugin_disconnect(PyDataIOPlugin *self, PyObject *args, PyObject* kwds);
static PyObject *PythonPlugins::PyDataIOPlugin_info(PyDataIOPlugin* self, PyObject* args);

static PyMemberDef PyDataIOPlugin_members[];
Expand Down
2 changes: 1 addition & 1 deletion Qitom/python/pythonQtConversion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2752,7 +2752,7 @@ PyObject* PythonQtConversion::QVariantListToPyObject(const QVariantList& l)
PyTuple_SET_ITEM(result, i, PythonQtConversion::QVariantToPyObject(v));
i++;
}
// why is the error state bad after this?
// todo: why is the error state bad after this?
PyErr_Clear();
return result;
}
Expand Down
42 changes: 33 additions & 9 deletions Qitom/python/pythonQtSignalMapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,14 +92,15 @@ PythonQtSignalMapper::~PythonQtSignalMapper()
\param [in] sigId is the Qt-internal ID of the signal (obtained by QMetaObject-system)
\param [in] callable is a reference to the real python method, that should act as slot. This method can be bounded or unbounded.
\param [in] argTypeList is a list of integer values that describe the Qt-internal type number for all arguments of the signal (type number with respect to QMetaType)
\param [in] minRepeatInterval is a minimum amount of time (in ms) which has to be passed until the same signal-slot-connection is accepted again (additional signal emissions are blocked), default: 0 (no timeout)
\return true if the connection could be established, else false.
*/
bool PythonQtSignalMapper::addSignalHandler(QObject *obj, const char* signal, int sigId, PyObject* callable, IntList &argTypeList)
bool PythonQtSignalMapper::addSignalHandler(QObject *obj, const char* signal, int sigId, PyObject* callable, IntList &argTypeList, int minRepeatInterval)
{
bool flag = false;
if (sigId>=0)
{
PythonQtSignalTarget t(argTypeList, m_slotCount, sigId, callable, signal);
PythonQtSignalTarget t(argTypeList, m_slotCount, sigId, callable, signal, minRepeatInterval);
m_targets.append(t);
// now connect to ourselves with the new slot id
if (QMetaObject::connect(obj, sigId, this, m_slotCount, Qt::AutoConnection, 0))
Expand Down Expand Up @@ -177,15 +178,20 @@ int PythonQtSignalMapper::qt_metacall(QMetaObject::Call c, int id, void **argume
QObject::qt_metacall(c, id, arguments);
}

foreach(const PythonQtSignalTarget& t, m_targets)
QList<PythonQtSignalTarget>::iterator it = m_targets.begin();

while (it != m_targets.end())
{
if (t.slotId() == id)
if (it->slotId() == id)
{
t.call(arguments);
it->call(arguments);
break;
}

++it;
}
return 0;

return 0;
}

//----------------------------------------------------------------------------------------------------------------------------------
Expand All @@ -203,10 +209,28 @@ int PythonQtSignalMapper::qt_metacall(QMetaObject::Call c, int id, void **argume
\param [in] arguments are the arguments of the emitted signal.
*/
void PythonQtSignalTarget::call(void ** arguments) const
void PythonQtSignalTarget::call(void ** arguments)
{
//qDebug() << "signaltarget::call in thread: " << QThread::currentThreadId ();

if (m_minRepeatInterval > 0)
{
if (m_elapsedTimer.isValid() == false)
{
//start the timer for the first time
m_elapsedTimer.start();
}
else
{
if (m_elapsedTimer.elapsed() < m_minRepeatInterval)
{
//the same signal has been fired to the same slot less than m_minRepeatInterval ms ago: ignore this call
return;
}
else
{
m_elapsedTimer.restart();
}
}
}

PythonEngine *pyEngine = qobject_cast<PythonEngine*>(AppManagement::getPythonEngine());

Expand Down
25 changes: 21 additions & 4 deletions Qitom/python/pythonQtSignalMapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@

#include <qvariant.h>
#include <qobject.h>
#include <qelapsedtimer.h>

namespace ito
{
Expand Down Expand Up @@ -72,17 +73,20 @@ class PythonQtSignalTarget
\param [in] signalId is the index of the emitting signal
\param [in] callabel is a python method or function (bounded or unbounded) that should be called if the slot is invoked
\param [in] signal is the signature of the signal (for debugging reasons)
\param [in] minRepeatInterval is a minimum amount of time (in ms) which has to be passed until the same signal-slot-connection is accepted again (additional signal emissions are blocked), default: 0 (no timeout)
*/
PythonQtSignalTarget(IntList &argTypeList, int slotId, int signalId, PyObject* callable, const char *signal) :
PythonQtSignalTarget(IntList &argTypeList, int slotId, int signalId, PyObject* callable, const char *signal, int minRepeatInterval) :
m_slotId(slotId),
m_signalId(signalId),
m_function(NULL),
m_boundedInstance(NULL),
m_boundedMethod(false),
m_signalName(signal)
m_signalName(signal),
m_minRepeatInterval(minRepeatInterval)
{
m_argTypeList = argTypeList;
PyObject *temp = NULL;
m_elapsedTimer.invalidate();

if(PyMethod_Check(callable))
{
Expand Down Expand Up @@ -123,6 +127,9 @@ class PythonQtSignalTarget
Py_XINCREF(m_function);
m_boundedInstance = copy.m_boundedInstance;
Py_XINCREF(m_boundedInstance);

m_minRepeatInterval = copy.m_minRepeatInterval;
m_elapsedTimer.invalidate();
}

//! destructor
Expand All @@ -140,7 +147,7 @@ class PythonQtSignalTarget
inline int slotId() const { return m_slotId; }

// call the python callable with the given arguments (docs see source file)
void call(void ** arguments) const;
void call(void ** arguments);

//! returns list of type-numbers of arguments
inline IntList argTypeList() const { return m_argTypeList; };
Expand Down Expand Up @@ -174,6 +181,15 @@ class PythonQtSignalTarget
PyObject *m_boundedInstance; //!< weak reference to the python-class instance of the function (if the function is bounded) or NULL if the function is unbounded
bool m_boundedMethod; //!< true if the python function is bounded (non-static member of a class), else false
QString m_signalName; //!< signature of the signal (mainly used for debugging reasons)
QElapsedTimer m_elapsedTimer; //!< see m_minRepeatInterval

/*
if > 0, every call of a certain slot by a certain signal with restart m_elapsedTimer. If the same signal-slot-connection is
called another time, while less than m_minRepeatInterval ms have expired, this new invoke will be ignored.
This can be used to prevent that very fast signal emissions will overflow the call queue for the connected callable python method.
*/
int m_minRepeatInterval;
};

/*! \class PythonQtSignalMapperBase
Expand Down Expand Up @@ -227,14 +243,15 @@ class PythonQtSignalMapper : public PythonQtSignalMapperBase
PythonQtSignalMapper();
~PythonQtSignalMapper();

bool addSignalHandler(QObject *obj, const char* signal, int sigId, PyObject* callable, IntList &argTypeList);
bool addSignalHandler(QObject *obj, const char* signal, int sigId, PyObject* callable, IntList &argTypeList, int minRepeatInterval);
bool removeSignalHandler(QObject *obj, const char* signal, int sigId, PyObject* callable);
void removeSignalHandlers();
virtual int qt_metacall(QMetaObject::Call c, int id, void **arguments);

private:
QList<PythonQtSignalTarget> m_targets; //!< list with all virtual slot targets that are the destination for any registered signal-slot-connection
int m_slotCount; //!< index of the last virtual slot managed by this instance (auto-incremented)

};

} //end namespace ito
Expand Down
21 changes: 13 additions & 8 deletions Qitom/python/pythonUi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -599,7 +599,7 @@ PyObject* PythonUi::PyUiItem_call(PyUiItem *self, PyObject* args)
}

//----------------------------------------------------------------------------------------------------------------------------------
PyDoc_STRVAR(PyUiItemConnect_doc,"connect(signalSignature, callableMethod) -> connects the signal of the widget with the given callable python method \n\
PyDoc_STRVAR(PyUiItemConnect_doc,"connect(signalSignature, callableMethod, minRepeatInterval = 0) -> connects the signal of the widget with the given callable python method \n\
\n\
This instance of *uiItem* wraps a widget, that is defined by a C++-class, that is finally derived from *QWidget*. See Qt-help for more information \n\
about the capabilities of every specific widget. Every widget can send various signals. Use this method to connect any signal to any \n\
Expand All @@ -612,16 +612,20 @@ signalSignature : {str} \n\
This must be the valid signature, known from the Qt-method *connect* (e.g. 'clicked(bool)') \n\
callableMethod : {python method or function} \n\
valid method or function that is called if the signal is emitted. \n\
minRepeatInterval : {int}, optional \n\
If > 0, the same signal only invokes a slot once within the given interval (in ms). Default: 0 (all signals will invoke the callable python method. \n\
\n\
See Also \n\
--------- \n\
disconnect, invokeKeyboardInterrupt");
PyObject* PythonUi::PyUiItem_connect(PyUiItem *self, PyObject* args)
PyObject* PythonUi::PyUiItem_connect(PyUiItem *self, PyObject* args, PyObject *kwds)
{
const char *kwlist[] = { "signalSignature", "callableMethod", "minRepeatInterval", NULL };
const char* signalSignature;
int minRepeatInterval = 0;
PyObject *callableMethod;

if(!PyArg_ParseTuple(args, "sO", &signalSignature, &callableMethod))
if(!PyArg_ParseTupleAndKeywords(args, kwds, "sO|i", const_cast<char**>(kwlist), &signalSignature, &callableMethod, &minRepeatInterval))
{
PyErr_SetString(PyExc_TypeError, "Arguments must be a signal signature and a callable method reference");
return NULL;
Expand Down Expand Up @@ -678,7 +682,7 @@ PyObject* PythonUi::PyUiItem_connect(PyUiItem *self, PyObject* args)
PythonQtSignalMapper *signalMapper = PyUiItem_getTopLevelSignalMapper(self);
if(signalMapper)
{
if(!signalMapper->addSignalHandler(*objPtr, signalSignature, *sigId, callableMethod, *argTypes))
if(!signalMapper->addSignalHandler(*objPtr, signalSignature, *sigId, callableMethod, *argTypes, minRepeatInterval))
{
PyErr_SetString(PyExc_RuntimeError, "the connection could not be established.");
return NULL;
Expand Down Expand Up @@ -767,12 +771,13 @@ See Also \n\
--------- \n\
connect \n\
");
PyObject* PythonUi::PyUiItem_disconnect(PyUiItem *self, PyObject* args)
PyObject* PythonUi::PyUiItem_disconnect(PyUiItem *self, PyObject* args, PyObject *kwds)
{
const char *kwlist[] = { "signalSignature", "callableMethod", NULL };
const char* signalSignature;
PyObject *callableMethod;

if(!PyArg_ParseTuple(args, "sO", &signalSignature, &callableMethod))
if (!PyArg_ParseTupleAndKeywords(args, kwds, "sO", const_cast<char**>(kwlist), &signalSignature, &callableMethod))
{
PyErr_SetString(PyExc_TypeError, "Arguments must be a signal signature and a callable method reference");
return NULL;
Expand Down Expand Up @@ -1702,8 +1707,8 @@ int PythonUi::PyUiItem_setattro(PyUiItem *self, PyObject *name, PyObject *value)
//----------------------------------------------------------------------------------------------------------------------------------
PyMethodDef PythonUi::PyUiItem_methods[] = {
{"call", (PyCFunction)PyUiItem_call, METH_VARARGS, PyUiItemCall_doc},
{"connect", (PyCFunction)PyUiItem_connect, METH_VARARGS, PyUiItemConnect_doc},
{"disconnect", (PyCFunction)PyUiItem_disconnect, METH_VARARGS, PyUiItemDisconnect_doc},
{"connect", (PyCFunction)PyUiItem_connect, METH_KEYWORDS | METH_VARARGS, PyUiItemConnect_doc},
{"disconnect", (PyCFunction)PyUiItem_disconnect, METH_KEYWORDS | METH_VARARGS, PyUiItemDisconnect_doc},
{"setProperty", (PyCFunction)PyUiItem_setProperties, METH_VARARGS, PyUiItemSetProperty_doc},
{"getProperty", (PyCFunction)PyUiItem_getProperties, METH_VARARGS, PyUiItemGetProperty_doc},
{"getPropertyInfo", (PyCFunction)PyUiItem_getPropertyInfo, METH_VARARGS, PyUiItemGetPropertyInfo_doc},
Expand Down
4 changes: 2 additions & 2 deletions Qitom/python/pythonUi.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,9 @@ class PythonUi
//-------------------------------------------------------------------------------------------------
static PyObject* PyUiItem_repr(PyUiItem *self);
static PyObject* PyUiItem_call(PyUiItem *self, PyObject* args);
static PyObject* PyUiItem_connect(PyUiItem *self, PyObject* args);
static PyObject* PyUiItem_connect(PyUiItem *self, PyObject* args, PyObject *kwds);
static PyObject* PyUiItem_connectKeyboardInterrupt(PyUiItem *self, PyObject* args);
static PyObject* PyUiItem_disconnect(PyUiItem *self, PyObject* args);
static PyObject* PyUiItem_disconnect(PyUiItem *self, PyObject* args, PyObject *kwds);
static PyObject* PyUiItem_getProperties(PyUiItem *self, PyObject *args);
static PyObject* PyUiItem_setProperties(PyUiItem *self, PyObject *args);
static PyObject *PyUiItem_getPropertyInfo(PyUiItem *self, PyObject *args);
Expand Down
Loading

0 comments on commit 72a6efe

Please sign in to comment.