+ move handwritten Python classes to PyCXX

This commit is contained in:
wmayer 2016-01-27 18:07:48 +01:00
parent dec030b34e
commit 173f19eff4
6 changed files with 131 additions and 187 deletions

View File

@ -319,7 +319,7 @@ void ProgressIndicatorPy::init_type()
behaviors().supportRepr(); behaviors().supportRepr();
behaviors().supportGetattr(); behaviors().supportGetattr();
behaviors().supportSetattr(); behaviors().supportSetattr();
behaviors().type_object()->tp_new = &PyMake; behaviors().set_tp_new(PyMake);
add_varargs_method("start",&ProgressIndicatorPy::start,"start(string,int)"); add_varargs_method("start",&ProgressIndicatorPy::start,"start(string,int)");
add_varargs_method("next",&ProgressIndicatorPy::next,"next()"); add_varargs_method("next",&ProgressIndicatorPy::next,"next()");

View File

@ -379,6 +379,7 @@ Application::Application(bool GUIenabled)
UiLoaderPy::init_type(); UiLoaderPy::init_type();
Base::Interpreter().addType(UiLoaderPy::type_object(), Base::Interpreter().addType(UiLoaderPy::type_object(),
module,"UiLoader"); module,"UiLoader");
PyResource::init_type();
// PySide additions // PySide additions
PySideUicModule* pySide = new PySideUicModule(); PySideUicModule* pySide = new PySideUicModule();

View File

@ -242,7 +242,7 @@ void SelectionFilterPy::init_type()
behaviors().supportRepr(); behaviors().supportRepr();
behaviors().supportGetattr(); behaviors().supportGetattr();
behaviors().supportSetattr(); behaviors().supportSetattr();
behaviors().type_object()->tp_new = &PyMake; behaviors().set_tp_new(PyMake);
add_varargs_method("match",&SelectionFilterPy::match,"match()"); add_varargs_method("match",&SelectionFilterPy::match,"match()");
add_varargs_method("result",&SelectionFilterPy::result,"result()"); add_varargs_method("result",&SelectionFilterPy::result,"result()");
add_varargs_method("test",&SelectionFilterPy::test,"test()"); add_varargs_method("test",&SelectionFilterPy::test,"test()");

View File

@ -568,7 +568,7 @@ void UiLoaderPy::init_type()
{ {
behaviors().name("UiLoader"); behaviors().name("UiLoader");
behaviors().doc("UiLoader to create widgets"); behaviors().doc("UiLoader to create widgets");
behaviors().type_object()->tp_new = &PyMake; behaviors().set_tp_new(PyMake);
// you must have overwritten the virtual functions // you must have overwritten the virtual functions
behaviors().supportRepr(); behaviors().supportRepr();
behaviors().supportGetattr(); behaviors().supportGetattr();
@ -879,59 +879,24 @@ ContainerDialog::~ContainerDialog()
// ---------------------------------------------------- // ----------------------------------------------------
//-------------------------------------------------------------------------- void PyResource::init_type()
// Type structure {
//-------------------------------------------------------------------------- behaviors().name("PyResource");
behaviors().doc("PyResource");
// you must have overwritten the virtual functions
behaviors().supportRepr();
behaviors().supportGetattr();
behaviors().supportSetattr();
add_varargs_method("value",&PyResource::value);
add_varargs_method("setValue",&PyResource::setValue);
add_varargs_method("show",&PyResource::show);
add_varargs_method("connect",&PyResource::connect);
}
PyTypeObject PyResource::Type = { PyResource::PyResource() : myDlg(0)
PyObject_HEAD_INIT(&PyType_Type)
0, /*ob_size*/
"PyResource", /*tp_name*/
sizeof(PyResource), /*tp_basicsize*/
0, /*tp_itemsize*/
/* methods */
PyDestructor, /*tp_dealloc*/
0, /*tp_print*/
__getattr, /*tp_getattr*/
__setattr, /*tp_setattr*/
0, /*tp_compare*/
__repr, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash*/
0, /*tp_call */
};
//--------------------------------------------------------------------------
// Methods structure
//--------------------------------------------------------------------------
PyMethodDef PyResource::Methods[] = {
{"GetValue", (PyCFunction) svalue, Py_NEWARGS},
{"SetValue", (PyCFunction) ssetValue, Py_NEWARGS},
{"Show", (PyCFunction) sshow, Py_NEWARGS},
{"Connect", (PyCFunction) sconnect, Py_NEWARGS},
{NULL, NULL} /* Sentinel */
};
//--------------------------------------------------------------------------
// constructor
//--------------------------------------------------------------------------
PyResource::PyResource(PyTypeObject *T)
: PyObjectBase(0, T), myDlg(0L)
{ {
} }
PyObject *PyResource::PyMake(PyObject *ignored, PyObject *args) // Python wrapper
{
//return new FCPyResource(); // Make new Python-able object
return 0;
}
//--------------------------------------------------------------------------
// FCPyResource destructor
//--------------------------------------------------------------------------
PyResource::~PyResource() PyResource::~PyResource()
{ {
delete myDlg; delete myDlg;
@ -941,27 +906,12 @@ PyResource::~PyResource()
} }
} }
//--------------------------------------------------------------------------
// FCPyParametrGrp Attributes
//--------------------------------------------------------------------------
PyObject *PyResource::_getattr(char *attr) // __getattr__ function: note only need to handle new state
{
_getattr_up(PyObjectBase); // send to parent
return 0;
}
int PyResource::_setattr(char *attr, PyObject *value) // __setattr__ function: note only need to handle new state
{
return PyObjectBase::_setattr(attr, value); // send up to parent
return 0;
}
/** /**
* Loads an .ui file with the name \a name. If the .ui file cannot be found or the QWidgetFactory * Loads an .ui file with the name \a name. If the .ui file cannot be found or the QWidgetFactory
* cannot create an instance an exception is thrown. If the created resource does not inherit from * cannot create an instance an exception is thrown. If the created resource does not inherit from
* QDialog an instance of ContainerDialog is created to embed it. * QDialog an instance of ContainerDialog is created to embed it.
*/ */
void PyResource::load( const char* name ) void PyResource::load(const char* name)
{ {
QString fn = QString::fromUtf8(name); QString fn = QString::fromUtf8(name);
QFileInfo fi(fn); QFileInfo fi(fn);
@ -1029,8 +979,8 @@ void PyResource::load( const char* name )
/** /**
* Makes a connection between the sender widget \a sender and its signal \a signal * Makes a connection between the sender widget \a sender and its signal \a signal
* of the created resource and Python callback function \a cb. * of the created resource and Python callback function \a cb.
* If the sender widget does not exist or no resource has been loaded this method returns false, * If the sender widget does not exist or no resource has been loaded this method returns FALSE,
* otherwise it returns true. * otherwise it returns TRUE.
*/ */
bool PyResource::connect(const char* sender, const char* signal, PyObject* cb) bool PyResource::connect(const char* sender, const char* signal, PyObject* cb)
{ {
@ -1041,7 +991,7 @@ bool PyResource::connect(const char* sender, const char* signal, PyObject* cb)
QList<QWidget*> list = myDlg->findChildren<QWidget*>(); QList<QWidget*> list = myDlg->findChildren<QWidget*>();
QList<QWidget*>::const_iterator it = list.begin(); QList<QWidget*>::const_iterator it = list.begin();
QObject *obj; QObject *obj;
QString sigStr = QString::fromLatin1("2%1").arg(QString::fromLatin1(signal)); QString sigStr = QString::fromAscii("2%1").arg(QString::fromAscii(signal));
while ( it != list.end() ) { while ( it != list.end() ) {
obj = *it; obj = *it;
@ -1055,7 +1005,7 @@ bool PyResource::connect(const char* sender, const char* signal, PyObject* cb)
if (objS) { if (objS) {
SignalConnect* sc = new SignalConnect(this, cb); SignalConnect* sc = new SignalConnect(this, cb);
mySingals.push_back(sc); mySingals.push_back(sc);
return QObject::connect(objS, sigStr.toLatin1(), sc, SLOT ( onExecute() ) ); return QObject::connect(objS, sigStr.toAscii(), sc, SLOT ( onExecute() ) );
} }
else else
qWarning( "'%s' does not exist.\n", sender ); qWarning( "'%s' does not exist.\n", sender );
@ -1063,64 +1013,12 @@ bool PyResource::connect(const char* sender, const char* signal, PyObject* cb)
return false; return false;
} }
/** Py::Object PyResource::repr()
* Searches for the sender, the signal and the callback function to connect with
* in the argument object \a args. In the case it fails 0 is returned.
*/
PyObject *PyResource::connect(PyObject *args)
{ {
char *psSender; std::string s;
char *psSignal; std::ostringstream s_out;
s_out << "Resource object";
PyObject *result = NULL; return Py::String(s_out.str());
PyObject *temp;
if (PyArg_ParseTuple(args, "ssOset_callback", &psSender, &psSignal, &temp)) {
if (!PyCallable_Check(temp)) {
PyErr_SetString(PyExc_TypeError, "parameter must be callable");
return NULL;
}
Py_XINCREF(temp); /* Add a reference to new callback */
std::string sSender = psSender;
std::string sSignal = psSignal;
if (!connect(psSender, psSignal, temp)) {
// no signal object found => dispose the callback object
Py_XDECREF(temp); /* Dispose of callback */
}
/* Boilerplate to return "None" */
Py_INCREF(Py_None);
result = Py_None;
}
return result;
}
/**
* If any resouce has been loaded this methods shows it as a modal dialog.
*/
PyObject *PyResource::show(PyObject *args)
{
if (myDlg) {
// small trick to get focus
myDlg->showMinimized();
#ifdef Q_WS_X11
// On X11 this may not work. For further information see QWidget::showMaximized
//
// workaround for X11
myDlg->hide();
myDlg->show();
#endif
myDlg->showNormal();
myDlg->exec();
}
Py_INCREF(Py_None);
return Py_None;
} }
/** /**
@ -1128,12 +1026,12 @@ PyObject *PyResource::show(PyObject *args)
* to returns its value as Python object. * to returns its value as Python object.
* In the case it fails 0 is returned. * In the case it fails 0 is returned.
*/ */
PyObject *PyResource::value(PyObject *args) Py::Object PyResource::value(const Py::Tuple& args)
{ {
char *psName; char *psName;
char *psProperty; char *psProperty;
if (!PyArg_ParseTuple(args, "ss", &psName, &psProperty)) // convert args: Python->C if (!PyArg_ParseTuple(args.ptr(), "ss", &psName, &psProperty))
return NULL; // NULL triggers exception throw Py::Exception();
QVariant v; QVariant v;
if (myDlg) { if (myDlg) {
@ -1156,42 +1054,42 @@ PyObject *PyResource::value(PyObject *args)
qWarning( "'%s' not found.\n", psName ); qWarning( "'%s' not found.\n", psName );
} }
PyObject *pItem=0; Py::Object item = Py::None();
switch (v.type()) switch (v.type())
{ {
case QVariant::StringList: case QVariant::StringList:
{ {
QStringList str = v.toStringList(); QStringList str = v.toStringList();
int nSize = str.count(); int nSize = str.count();
PyObject* slist = PyList_New(nSize); Py::List slist(nSize);
for (int i=0; i<nSize;++i) { for (int i=0; i<nSize;++i) {
PyObject* item = PyString_FromString(str[i].toLatin1()); slist.setItem(i, Py::String(str[i].toAscii()));
PyList_SetItem(slist, i, item);
} }
item = slist;
} break; } break;
case QVariant::ByteArray: case QVariant::ByteArray:
break; break;
case QVariant::String: case QVariant::String:
pItem = PyString_FromString(v.toString().toLatin1()); item = Py::String(v.toString().toAscii());
break; break;
case QVariant::Double: case QVariant::Double:
pItem = PyFloat_FromDouble(v.toDouble()); item = Py::Float(v.toDouble());
break; break;
case QVariant::Bool: case QVariant::Bool:
pItem = PyInt_FromLong(v.toBool() ? 1 : 0); item = Py::Boolean(v.toBool() ? 1 : 0);
break; break;
case QVariant::UInt: case QVariant::UInt:
pItem = PyLong_FromLong(v.toUInt()); item = Py::Long(static_cast<unsigned long>(v.toUInt()));
break; break;
case QVariant::Int: case QVariant::Int:
pItem = PyInt_FromLong(v.toInt()); item = Py::Int(v.toInt());
break; break;
default: default:
pItem = PyString_FromString(""); item = Py::String("");
break; break;
} }
return pItem; return item;
} }
/** /**
@ -1199,17 +1097,17 @@ PyObject *PyResource::value(PyObject *args)
* to set even this new value. * to set even this new value.
* In the case it fails 0 is returned. * In the case it fails 0 is returned.
*/ */
PyObject *PyResource::setValue(PyObject *args) Py::Object PyResource::setValue(const Py::Tuple& args)
{ {
char *psName; char *psName;
char *psProperty; char *psProperty;
PyObject *psValue; PyObject *psValue;
if (!PyArg_ParseTuple(args, "ssO", &psName, &psProperty, &psValue)) // convert args: Python->C if (!PyArg_ParseTuple(args.ptr(), "ssO", &psName, &psProperty, &psValue))
return NULL; // NULL triggers exception throw Py::Exception();
QVariant v; QVariant v;
if (PyString_Check(psValue)) { if (PyString_Check(psValue)) {
v = QString::fromLatin1(PyString_AsString(psValue)); v = QString::fromAscii(PyString_AsString(psValue));
} }
else if (PyInt_Check(psValue)) { else if (PyInt_Check(psValue)) {
int val = PyInt_AsLong(psValue); int val = PyInt_AsLong(psValue);
@ -1231,14 +1129,13 @@ PyObject *PyResource::setValue(PyObject *args)
continue; continue;
char* pItem = PyString_AsString(item); char* pItem = PyString_AsString(item);
str.append(QString::fromLatin1(pItem)); str.append(QString::fromAscii(pItem));
} }
v = str; v = str;
} }
else { else {
PyErr_SetString(PyExc_AssertionError, "Unsupported type"); throw Py::TypeError("Unsupported type");
return NULL;
} }
if (myDlg) { if (myDlg) {
@ -1257,23 +1154,80 @@ PyObject *PyResource::setValue(PyObject *args)
} }
} }
if ( !fnd ) if (!fnd)
qWarning( "'%s' not found.\n", psName ); qWarning( "'%s' not found.\n", psName );
} }
Py_INCREF(Py_None); return Py::None();
return Py_None; }
/**
* If any resouce has been loaded this methods shows it as a modal dialog.
*/
Py::Object PyResource::show(const Py::Tuple& args)
{
if (myDlg) {
// small trick to get focus
myDlg->showMinimized();
#ifdef Q_WS_X11
// On X11 this may not work. For further information see QWidget::showMaximized
//
// workaround for X11
myDlg->hide();
myDlg->show();
#endif
myDlg->showNormal();
myDlg->exec();
}
return Py::None();
}
/**
* Searches for the sender, the signal and the callback function to connect with
* in the argument object \a args. In the case it fails 0 is returned.
*/
Py::Object PyResource::connect(const Py::Tuple& args)
{
char *psSender;
char *psSignal;
PyObject *temp;
if (PyArg_ParseTuple(args.ptr(), "ssO", &psSender, &psSignal, &temp)) {
if (!PyCallable_Check(temp)) {
PyErr_SetString(PyExc_TypeError, "parameter must be callable");
throw Py::Exception();
}
Py_XINCREF(temp); /* Add a reference to new callback */
std::string sSender = psSender;
std::string sSignal = psSignal;
if (!connect(psSender, psSignal, temp)) {
// no signal object found => dispose the callback object
Py_XDECREF(temp); /* Dispose of callback */
}
return Py::None();
}
// error set by PyArg_ParseTuple
throw Py::Exception();
} }
// ---------------------------------------------------- // ----------------------------------------------------
SignalConnect::SignalConnect(Base::PyObjectBase* res, PyObject* cb) SignalConnect::SignalConnect(PyObject* res, PyObject* cb)
: myResource(res), myCallback(cb) : myResource(res), myCallback(cb)
{ {
} }
SignalConnect::~SignalConnect() SignalConnect::~SignalConnect()
{ {
Base::PyGILStateLocker lock;
Py_XDECREF(myCallback); /* Dispose of callback */ Py_XDECREF(myCallback); /* Dispose of callback */
} }
@ -1288,7 +1242,7 @@ void SignalConnect::onExecute()
/* Time to call the callback */ /* Time to call the callback */
arglist = Py_BuildValue("(O)", myResource); arglist = Py_BuildValue("(O)", myResource);
result = PyEval_CallObject(myCallback, arglist); result = PyEval_CallObject(myCallback, arglist);
(void)result; Py_XDECREF(result);
Py_DECREF(arglist); Py_DECREF(arglist);
} }

View File

@ -351,7 +351,7 @@ private:
* The PyResource class provides an interface to create widgets or to load .ui files from Python. * The PyResource class provides an interface to create widgets or to load .ui files from Python.
* With * With
* \code * \code
* d = Gui.CreateDialog("test.ui") * d = Gui.createDialog("test.ui")
* \endcode * \endcode
* *
* you can create a PyResource object containing the widget. If a relative file name * you can create a PyResource object containing the widget. If a relative file name
@ -374,12 +374,12 @@ private:
* # define a callback function with one argument * # define a callback function with one argument
* def TestCall(obj): * def TestCall(obj):
* # sets the value from lineedit if "Button_Name" was pressed * # sets the value from lineedit if "Button_Name" was pressed
* obj.SetValue("lineedit", "text", "Show this text here!") * obj.setValue("lineedit", "text", "Show this text here!")
* print "Button clicked" * print "Button clicked"
* *
* d = Gui.CreateDialog("test.ui") * d = Gui.createDialog("test.ui")
* d.Connect("Button_Name", "clicked()", TestCall) * d.connect("Button_Name", "clicked()", TestCall)
* d.Show() * d.show()
* \endcode * \endcode
* *
* If the button with the name "Button_Name" is clicked the message "Button clicked" is * If the button with the name "Button_Name" is clicked the message "Button clicked" is
@ -387,47 +387,36 @@ private:
* For example if you have a QLineEdit inside your widget you can set the text with * For example if you have a QLineEdit inside your widget you can set the text with
* \code * \code
* # sets "Show this text here!" to the text property * # sets "Show this text here!" to the text property
* d.SetValue("lineedit", "text", "Show this text here!") * d.setValue("lineedit", "text", "Show this text here!")
* d.Show() * d.show()
* \endcode * \endcode
* *
* or retrieve the entered text with * or retrieve the entered text with
* \code * \code
* f = d.GetValue("lineedit", "text") * f = d.getValue("lineedit", "text")
* print f * print f
* \endcode * \endcode
* *
* \author Werner Mayer * \author Werner Mayer
*/ */
class PyResource : public Base::PyObjectBase
class PyResource : public Py::PythonExtension<PyResource>
{ {
// always start with Py_Header
Py_Header;
protected:
~PyResource();
public: public:
PyResource(PyTypeObject *T = &Type); static void init_type(void); // announce properties and methods
PyResource();
~PyResource();
void load(const char* name); void load(const char* name);
bool connect(const char* sender, const char* signal, PyObject* cb); bool connect(const char* sender, const char* signal, PyObject* cb);
/// for construction in Python Py::Object repr();
static PyObject *PyMake(PyObject *, PyObject *);
//--------------------------------------------------------------------- Py::Object value(const Py::Tuple&);
// python exports goes here +++++++++++++++++++++++++++++++++++++++++++ Py::Object setValue(const Py::Tuple&);
//--------------------------------------------------------------------- Py::Object show(const Py::Tuple&);
PyObject *_getattr(char *attr); // __getattr__ function Py::Object connect(const Py::Tuple&);
// getter setter
int _setattr(char *attr, PyObject *value); // __setattr__ function
// methods
PYFUNCDEF_D(PyResource, value);
PYFUNCDEF_D(PyResource, setValue);
PYFUNCDEF_D(PyResource, show);
PYFUNCDEF_D(PyResource, connect);
private: private:
std::vector<class SignalConnect*> mySingals; std::vector<class SignalConnect*> mySingals;
@ -445,7 +434,7 @@ class SignalConnect : public QObject
Q_OBJECT Q_OBJECT
public: public:
SignalConnect(Base::PyObjectBase* res, PyObject* cb); SignalConnect(PyObject* res, PyObject* cb);
~SignalConnect(); ~SignalConnect();
public Q_SLOTS: public Q_SLOTS:

View File

@ -83,7 +83,7 @@ void SMESH_HypothesisPy<T>::init_type(PyObject* module)
SMESH_HypothesisPy<T>::behaviors().supportRepr(); SMESH_HypothesisPy<T>::behaviors().supportRepr();
SMESH_HypothesisPy<T>::behaviors().supportGetattr(); SMESH_HypothesisPy<T>::behaviors().supportGetattr();
SMESH_HypothesisPy<T>::behaviors().supportSetattr(); SMESH_HypothesisPy<T>::behaviors().supportSetattr();
SMESH_HypothesisPy<T>::behaviors().type_object()->tp_new = &PyMake; SMESH_HypothesisPy<T>::behaviors().set_tp_new(PyMake);
SMESH_HypothesisPy::add_varargs_method("setLibName", &SMESH_HypothesisPy<T>::setLibName, "setLibName(String)"); SMESH_HypothesisPy::add_varargs_method("setLibName", &SMESH_HypothesisPy<T>::setLibName, "setLibName(String)");
SMESH_HypothesisPy::add_varargs_method("getLibName", &SMESH_HypothesisPy<T>::getLibName, "String getLibName()"); SMESH_HypothesisPy::add_varargs_method("getLibName", &SMESH_HypothesisPy<T>::getLibName, "String getLibName()");