|
|
|
/***************************************************************************
|
|
|
|
* Copyright (C) 2003 by Julian Rockey (linux@jrockey.com) *
|
|
|
|
* Original code by Torben Weis *
|
|
|
|
* *
|
|
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
|
|
* it under the terms of the GNU General Public License as published by *
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
|
|
* (at your option) any later version. *
|
|
|
|
***************************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
#include "pcop.h"
|
|
|
|
|
|
|
|
#include <kdebug.h>
|
|
|
|
|
|
|
|
#include <tqapplication.h>
|
|
|
|
#include <tqcstring.h>
|
|
|
|
#include <tqdatastream.h>
|
|
|
|
#include <tqfile.h>
|
|
|
|
#include <tqtextstream.h>
|
|
|
|
#include <tqstring.h>
|
|
|
|
|
|
|
|
#include <dcopclient.h>
|
|
|
|
|
|
|
|
#include <assert.h>
|
|
|
|
|
|
|
|
#include "marshaller.h"
|
|
|
|
#include "importedmodules.h"
|
|
|
|
|
|
|
|
namespace PythonDCOP {
|
|
|
|
|
|
|
|
PCOPObject::PCOPObject(PyObject *py_obj) :
|
|
|
|
DCOPObject(), m_py_obj(py_obj)
|
|
|
|
{
|
|
|
|
m_methods.setAutoDelete(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
PCOPObject::PCOPObject(PyObject *py_obj, const char *objid) :
|
|
|
|
DCOPObject(TTQCString(objid)), m_py_obj(py_obj)
|
|
|
|
{
|
|
|
|
m_methods.setAutoDelete(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
PCOPObject::~PCOPObject()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
bool PCOPObject::process(const TTQCString &fun, const TTQByteArray &data,
|
|
|
|
TTQCString& replyType, TTQByteArray &replyData)
|
|
|
|
{
|
|
|
|
bool result = py_process(fun,data,replyType,replyData);
|
|
|
|
if (PyErr_Occurred()) {
|
|
|
|
kdDebug(70001) << "Error! About to print..." << endl;
|
|
|
|
PyErr_Print();
|
|
|
|
kdDebug(70001) << "About to clear..." << endl;
|
|
|
|
PyErr_Clear();
|
|
|
|
kdDebug(70001) << "Error handled." << endl;
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool PCOPObject::py_process(const TTQCString &fun, const TTQByteArray &data,
|
|
|
|
TTQCString& replyType, TTQByteArray &replyData)
|
|
|
|
{
|
|
|
|
|
|
|
|
kdDebug(70001) << "PCOPObject::process - fun=" << fun << " replyType=" << replyType << endl;
|
|
|
|
|
|
|
|
PCOPMethod *meth = matchMethod(fun);
|
|
|
|
if (!meth) {
|
|
|
|
kdDebug(70001) << "Could not match method name" << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (meth) {
|
|
|
|
|
|
|
|
kdDebug(70001) << "m_py_obj=" << m_py_obj << " meth->name=" << meth->name() << " meth->name.data=" << meth->name().data() << endl;
|
|
|
|
if (meth->name().isNull()) { kdDebug(70001) << "meth name is null" << endl; return false; }
|
|
|
|
// if (!PyObject_HasAttrString(m_py_obj, meth->name().data())) {
|
|
|
|
// kdDebug(70001) << "Method registered, but no python method found" << endl;
|
|
|
|
// return false;
|
|
|
|
// }
|
|
|
|
|
|
|
|
TTQDataStream str_arg(data, IO_ReadOnly);
|
|
|
|
PyObject *args = PyTuple_New( meth->paramCount() );
|
|
|
|
for(int c=0;c<meth->paramCount();c++) {
|
|
|
|
kdDebug(70001) << "Demarshalling type: " << meth->param(c)->signature() << endl;
|
|
|
|
PyObject *arg = meth->param(c)->demarshal(str_arg);
|
|
|
|
if (!arg) {
|
|
|
|
kdDebug(70001) << "Failed to demarshall an argument" << endl;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
PyTuple_SetItem(args, c, arg );
|
|
|
|
}
|
|
|
|
|
|
|
|
kdDebug(70001) << "args is " << PyTuple_Size(args) << " long" << endl;
|
|
|
|
|
|
|
|
// PyObject *method = PyObject_GetAttrString(m_py_obj, meth->name().data() );
|
|
|
|
PyObject *method = meth->pythonMethod();
|
|
|
|
if (!PyCallable_Check(method)) {
|
|
|
|
kdDebug(70001) << "Expected a callable object, but didn't get one!" << endl;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// PyObject *function = PyMethod_Function(method);
|
|
|
|
// PyObject *self = PyMethod_Self(method);
|
|
|
|
// Py_INCREF(self);
|
|
|
|
// PyTuple_SetItem(args, 0, self );
|
|
|
|
// PyObject *result = PyObject_CallObject(function, args);
|
|
|
|
|
|
|
|
// Py_DECREF(method);
|
|
|
|
if (PyMethod_Self(method)==NULL)
|
|
|
|
kdDebug(70001) << "Warning: self is null!" << endl;
|
|
|
|
|
|
|
|
kdDebug(70001) << "About to call object.." << endl;
|
|
|
|
PyObject *result = PyObject_CallObject(method, args);
|
|
|
|
kdDebug(70001) << "Finished calling object." << endl;
|
|
|
|
|
|
|
|
if (result) {
|
|
|
|
replyType = meth->type()->signature();
|
|
|
|
PCOPType repl(replyType);
|
|
|
|
if (repl.isMarshallable(result)) {
|
|
|
|
TTQDataStream str_repl(replyData, IO_WriteOnly);
|
|
|
|
repl.marshal(result,str_repl);
|
|
|
|
Py_DECREF(result);
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
Py_DECREF(result);
|
|
|
|
kdDebug(70001) << "Result of python method was not marshallable into " << replyType << endl;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
kdDebug(70001) << "null result from python method call" << endl;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return DCOPObject::process(fun,data,replyType,replyData);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
bool PCOPObject::setMethodList(TTQAsciiDict<PyObject> meth_list) {
|
|
|
|
bool ok = true;
|
|
|
|
|
|
|
|
for(TTQAsciiDictIterator<PyObject> it(meth_list);
|
|
|
|
it.current(); ++it) {
|
|
|
|
|
|
|
|
PCOPMethod *meth = NULL;
|
|
|
|
if (ok) {
|
|
|
|
meth = new PCOPMethod(TTQCString(it.currentKey()));
|
|
|
|
|
|
|
|
if (!meth || !meth->setPythonMethod(it.current())) {
|
|
|
|
if (meth) delete meth;
|
|
|
|
meth=NULL;
|
|
|
|
m_methods.clear();
|
|
|
|
ok=false;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// Py_DECREF(it.current());
|
|
|
|
if (meth) m_methods.insert(meth->signature(),meth);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ok;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQCStringList PCOPObject::functions() {
|
|
|
|
TQCStringList funcs = DCOPObject::functions();
|
|
|
|
for(TTQAsciiDictIterator<PCOPMethod> it(m_methods);
|
|
|
|
it.current(); ++it) {
|
|
|
|
PCOPMethod *meth = it.current();
|
|
|
|
TTQCString func = meth->type()->signature();
|
|
|
|
func += ' ';
|
|
|
|
func += meth->signature();
|
|
|
|
funcs << func;
|
|
|
|
}
|
|
|
|
return funcs;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* For testing
|
|
|
|
*/
|
|
|
|
PyObject *PCOPObject::methodList() {
|
|
|
|
PyObject *result = PyList_New(m_methods.count());
|
|
|
|
int c=0;
|
|
|
|
for(TTQAsciiDictIterator<PCOPMethod> it(m_methods);
|
|
|
|
it.current(); ++it, ++c) {
|
|
|
|
PyObject *tuple = PyTuple_New(2);
|
|
|
|
PyList_SetItem(result, c, tuple);
|
|
|
|
PyTuple_SetItem(tuple, 0, PyString_FromString(it.currentKey() ) );
|
|
|
|
PyTuple_SetItem(tuple, 1, it.current()->pythonMethod() );
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
PCOPMethod *PCOPObject::matchMethod(const TTQCString &fun) {
|
|
|
|
return m_methods.find(fun);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
PCOPType::PCOPType( const TTQCString& type )
|
|
|
|
{
|
|
|
|
m_leftType = NULL;
|
|
|
|
m_rightType = NULL;
|
|
|
|
|
|
|
|
int pos = type.find( '<' );
|
|
|
|
if ( pos == -1 )
|
|
|
|
{
|
|
|
|
m_type = type;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
int pos2 = type.findRev( '>' );
|
|
|
|
if ( pos2 == -1 )
|
|
|
|
return;
|
|
|
|
|
|
|
|
m_type = type.left( pos );
|
|
|
|
|
|
|
|
// There may be no more than 2 types in the bracket
|
|
|
|
int komma = type.find( ',', pos + 1 );
|
|
|
|
if ( komma == -1 )
|
|
|
|
{
|
|
|
|
m_leftType = new PCOPType( type.mid( pos + 1, pos2 - pos - 1 ) );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_leftType = new PCOPType( type.mid( pos + 1, komma - pos - 1 ) );
|
|
|
|
m_rightType = new PCOPType( type.mid( komma + 1, pos2 - komma - 1 ) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
PCOPType::~PCOPType()
|
|
|
|
{
|
|
|
|
if (m_leftType) delete m_leftType;
|
|
|
|
if (m_rightType) delete m_rightType;
|
|
|
|
}
|
|
|
|
|
|
|
|
TTQCString PCOPType::signature() const
|
|
|
|
{
|
|
|
|
TTQCString str = m_type;
|
|
|
|
if ( m_leftType )
|
|
|
|
{
|
|
|
|
str += "<";
|
|
|
|
str += m_leftType->signature();
|
|
|
|
|
|
|
|
if ( m_rightType )
|
|
|
|
{
|
|
|
|
str += ",";
|
|
|
|
str += m_rightType->signature();
|
|
|
|
}
|
|
|
|
|
|
|
|
str += ">";
|
|
|
|
}
|
|
|
|
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool PCOPType::marshal( PyObject* obj, TTQDataStream& str ) const
|
|
|
|
{
|
|
|
|
return Marshaller::instance()->marshal(*this, obj, str);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool PCOPType::isMarshallable( PyObject *obj ) const
|
|
|
|
{
|
|
|
|
return Marshaller::instance()->canMarshal(*this, obj);
|
|
|
|
}
|
|
|
|
|
|
|
|
PyObject* PCOPType::demarshal( TTQDataStream& str ) const
|
|
|
|
{
|
|
|
|
return Marshaller::instance()->demarshal(*this, str);
|
|
|
|
}
|
|
|
|
|
|
|
|
PCOPMethod::PCOPMethod( const TTQCString& signature ) :
|
|
|
|
m_py_method(NULL)
|
|
|
|
{
|
|
|
|
|
|
|
|
m_type = 0;
|
|
|
|
m_params.setAutoDelete( TRUE );
|
|
|
|
|
|
|
|
// Find the space that separates the type from the name
|
|
|
|
int k = signature.find( ' ' );
|
|
|
|
if ( k == -1 )
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Create the return type from the string
|
|
|
|
m_type = new PCOPType( signature.left( k ) );
|
|
|
|
|
|
|
|
// Find the brackets
|
|
|
|
int i = signature.find( '(' );
|
|
|
|
if ( i == -1 )
|
|
|
|
return;
|
|
|
|
int j = signature.find( ')' );
|
|
|
|
if ( j == -1 )
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Extract the name
|
|
|
|
m_name = signature.mid( k + 1, i - k - 1 );
|
|
|
|
|
|
|
|
// Strip the parameters
|
|
|
|
TTQCString p = signature.mid( i + 1, j - i - 1 ).stripWhiteSpace();
|
|
|
|
|
|
|
|
if ( !p.isEmpty() ) {
|
|
|
|
// Make the algorithm terminate
|
|
|
|
p += ",";
|
|
|
|
|
|
|
|
// Iterate over the parameters
|
|
|
|
int level = 0;
|
|
|
|
int start = 0;
|
|
|
|
int len = p.length();
|
|
|
|
for( int i = 0; i < len; ++i )
|
|
|
|
{
|
|
|
|
// Found a comma? Then we reached the end of a parameter
|
|
|
|
if ( p[i] == ',' && level == 0 )
|
|
|
|
{
|
|
|
|
// Find the space that separates name from type.
|
|
|
|
int space = p.find( ' ', start );
|
|
|
|
|
|
|
|
if ( space == -1 || space > i ) // unnamed parameter
|
|
|
|
space = i;
|
|
|
|
|
|
|
|
PCOPType* type = new PCOPType( p.mid( start, space - start ) );
|
|
|
|
m_params.append( type );
|
|
|
|
|
|
|
|
// Start of the next parameter
|
|
|
|
start = i + 1;
|
|
|
|
}
|
|
|
|
else if ( p[i] == '<' )
|
|
|
|
++level;
|
|
|
|
else if ( p[i] == '>' )
|
|
|
|
--level;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
m_signature = m_name;
|
|
|
|
m_signature += "(";
|
|
|
|
|
|
|
|
TQListIterator<PCOPType> it( m_params );
|
|
|
|
for( ; it.current(); ++it )
|
|
|
|
{
|
|
|
|
if ( !it.atFirst() )
|
|
|
|
m_signature += ',';
|
|
|
|
m_signature += it.current()->signature();
|
|
|
|
}
|
|
|
|
|
|
|
|
m_signature += ")";
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
PCOPMethod::~PCOPMethod()
|
|
|
|
{
|
|
|
|
delete m_type;
|
|
|
|
if (m_py_method) {
|
|
|
|
Py_DECREF(m_py_method);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool PCOPMethod::setPythonMethod(PyObject *method) {
|
|
|
|
if (method && PyMethod_Check(method)) {
|
|
|
|
|
|
|
|
if (m_py_method) {
|
|
|
|
Py_DECREF(m_py_method);
|
|
|
|
}
|
|
|
|
|
|
|
|
m_py_method = method;
|
|
|
|
Py_INCREF(m_py_method);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
int PCOPMethod::paramCount() const
|
|
|
|
{
|
|
|
|
return m_params.count();
|
|
|
|
}
|
|
|
|
|
|
|
|
PCOPType* PCOPMethod::param( int i )
|
|
|
|
{
|
|
|
|
return m_params.at( i );
|
|
|
|
}
|
|
|
|
|
|
|
|
const PCOPType* PCOPMethod::param( int i ) const
|
|
|
|
{
|
|
|
|
return ((PCOPMethod*)this)->m_params.at( i );
|
|
|
|
}
|
|
|
|
|
|
|
|
PCOPClass::PCOPClass( const TQCStringList& methods )
|
|
|
|
{
|
|
|
|
m_methods.setAutoDelete( true );
|
|
|
|
|
|
|
|
TQCStringList::ConstIterator it = methods.begin();
|
|
|
|
for( ; it != methods.end(); ++it )
|
|
|
|
{
|
|
|
|
PCOPMethod* m = new PCOPMethod( *it );
|
|
|
|
m_methods.insert( m->m_name, m );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
PCOPClass::~PCOPClass()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
const PCOPMethod* PCOPClass::method( const TTQCString &name, PyObject *argTuple )
|
|
|
|
{
|
|
|
|
if ( !argTuple )
|
|
|
|
return m_methods[ name ];
|
|
|
|
|
|
|
|
TTQAsciiDictIterator<PCOPMethod> it( m_methods );
|
|
|
|
for (; it.current(); ++it )
|
|
|
|
if ( it.currentKey() == name &&
|
|
|
|
it.current()->paramCount() == PyTuple_Size( argTuple ) )
|
|
|
|
{
|
|
|
|
// ok, name and argument count match, now check if the python
|
|
|
|
// can be marshalled to the qt/dcop type
|
|
|
|
|
|
|
|
PCOPMethod *m = it.current();
|
|
|
|
|
|
|
|
bool fullMatch = true;
|
|
|
|
|
|
|
|
for ( int i = 0; i < m->paramCount(); ++i )
|
|
|
|
if ( !m->param( i )->isMarshallable( PyTuple_GetItem( argTuple, i ) ) )
|
|
|
|
{
|
|
|
|
fullMatch = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( fullMatch )
|
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Client
|
|
|
|
|
|
|
|
Client::Client() : m_dcop(NULL), m_qapp(NULL)
|
|
|
|
{
|
|
|
|
ImportedModules::setInstance( new ImportedModules );
|
|
|
|
int argc = 0;
|
|
|
|
char **argv = NULL;
|
|
|
|
m_qapp = new TTQApplication(argc,argv,false);
|
|
|
|
}
|
|
|
|
|
|
|
|
Client::~Client()
|
|
|
|
{
|
|
|
|
// if (m_qapp) delete m_qapp;
|
|
|
|
if (m_dcop) delete m_dcop;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Client::processEvents() {
|
|
|
|
if (m_qapp) {
|
|
|
|
// kdDebug(70001) << "Processing events..." << endl;
|
|
|
|
m_qapp->processEvents();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
DCOPClient *Client::dcop() {
|
|
|
|
if ( !m_dcop ) {
|
|
|
|
m_dcop = new DCOPClient;
|
|
|
|
if ( !m_dcop->attach() )
|
|
|
|
kdWarning(70001) << "Could not attach to DCOP server";
|
|
|
|
}
|
|
|
|
return m_dcop;
|
|
|
|
}
|
|
|
|
|
|
|
|
Client *Client::instance() { return s_instance; }
|
|
|
|
Client *Client::s_instance = new Client;
|
|
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Methods accessed by python
|
|
|
|
//
|
|
|
|
////////////////////////////////////////////////
|
|
|
|
|
|
|
|
PyObject* dcop_call( PyObject* /*self*/, PyObject* args )
|
|
|
|
{
|
|
|
|
char *arg1;
|
|
|
|
char *arg2;
|
|
|
|
char *arg3;
|
|
|
|
PyObject* tuple;
|
|
|
|
|
|
|
|
if ( !PyArg_ParseTuple( args, (char*)"sssO", &arg1, &arg2, &arg3, &tuple ) )
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if ( !PyTuple_Check( tuple ) )
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
TTQByteArray replyData;
|
|
|
|
TTQCString replyType;
|
|
|
|
TTQByteArray data;
|
|
|
|
TTQDataStream params( data, IO_WriteOnly );
|
|
|
|
|
|
|
|
TTQCString appname( arg1 );
|
|
|
|
TTQCString objname( arg2 );
|
|
|
|
TTQCString funcname( arg3 );
|
|
|
|
|
|
|
|
//
|
|
|
|
// Remove escape characters
|
|
|
|
//
|
|
|
|
if ( objname[0] == '_' )
|
|
|
|
objname = objname.mid( 1 );
|
|
|
|
if ( funcname[0] == '_' )
|
|
|
|
funcname = funcname.mid( 1 );
|
|
|
|
|
|
|
|
DCOPClient* dcop = Client::instance()->dcop();
|
|
|
|
|
|
|
|
//
|
|
|
|
// Determine which functions are available.
|
|
|
|
//
|
|
|
|
bool ok = false;
|
|
|
|
TQCStringList funcs = dcop->remoteFunctions( appname, objname, &ok );
|
|
|
|
if ( !ok )
|
|
|
|
{
|
|
|
|
PyErr_SetString( PyExc_RuntimeError, "Object is not accessible." );
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
// for ( TQCStringList::Iterator it = funcs.begin(); it != funcs.end(); ++it ) {
|
|
|
|
// qDebug( "%s", (*it).data() );
|
|
|
|
// }
|
|
|
|
|
|
|
|
//
|
|
|
|
// Create a parse tree and search for the method
|
|
|
|
//
|
|
|
|
// ### Check wether that is sane
|
|
|
|
PCOPClass c( funcs );
|
|
|
|
|
|
|
|
// qDebug("Parsing done.");
|
|
|
|
|
|
|
|
// Does the requested method exist ?
|
|
|
|
const PCOPMethod* m = c.method( funcname, tuple );
|
|
|
|
if ( !m )
|
|
|
|
{
|
|
|
|
PyErr_SetString( PyExc_RuntimeError, "DCOP: Unknown method." );
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
TTQCString signature = m->signature();
|
|
|
|
kdDebug(70001) << "The signature is " << signature.data() << endl;
|
|
|
|
|
|
|
|
kdDebug(70001) << "The method takes " << m->paramCount() << " parameters" << endl;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Marshal the parameters.
|
|
|
|
//
|
|
|
|
|
|
|
|
int param_count = m->paramCount();
|
|
|
|
for( int p = 0; p < param_count; ++p )
|
|
|
|
{
|
|
|
|
PyObject* o = PyTuple_GetItem( tuple, p );
|
|
|
|
// #### Check for errors
|
|
|
|
if ( !m->param( p )->marshal( o, params ) )
|
|
|
|
{
|
|
|
|
kdDebug(70001) << "QD: Could not marshal paramater %i" << p << endl;
|
|
|
|
PyErr_SetString( PyExc_RuntimeError, "DCOP: marshaling failed" );
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
kdDebug(70001) << "Calling " << appname.data() << " " << objname.data() << " " << signature.data() << endl;
|
|
|
|
|
|
|
|
// ASSERT( Client::instance()->dcop() != 0 );
|
|
|
|
ASSERT(dcop);
|
|
|
|
|
|
|
|
if ( !dcop->call( appname, objname, signature, data, replyType, replyData ) )
|
|
|
|
{
|
|
|
|
PyErr_SetString( PyExc_RuntimeError, "DCOP: call failed" );
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
kdDebug(70001) << "The return type is " << replyType.data() << endl;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Now decode the return type.
|
|
|
|
//
|
|
|
|
// ### Check wether that was sane
|
|
|
|
PCOPType type( replyType );
|
|
|
|
TTQDataStream reply(replyData, IO_ReadOnly);
|
|
|
|
return type.demarshal( reply );
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
PyObject* application_list( PyObject */*self*/, PyObject */*args*/ )
|
|
|
|
{
|
|
|
|
TQCStringList apps = Client::instance()->dcop()->registeredApplications();
|
|
|
|
|
|
|
|
PyObject *l = PyList_New( apps.count() );
|
|
|
|
|
|
|
|
TQCStringList::ConstIterator it = apps.begin();
|
|
|
|
TQCStringList::ConstIterator end = apps.end();
|
|
|
|
unsigned int i = 0;
|
|
|
|
for (; it != end; ++it, i++ )
|
|
|
|
PyList_SetItem( l, i, PyString_FromString( (*it).data() ) );
|
|
|
|
|
|
|
|
return l;
|
|
|
|
}
|
|
|
|
|
|
|
|
PyObject *object_list( PyObject */*self*/, PyObject *args) {
|
|
|
|
const char *app;
|
|
|
|
if (PyArg_ParseTuple(args, (char*)"s", &app)) {
|
|
|
|
TQCStringList objects = Client::instance()->dcop()->remoteObjects(TTQCString(app));
|
|
|
|
return make_py_list(objects);
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
PyObject *method_list( PyObject */*self*/, PyObject *args) {
|
|
|
|
const char *app, *obj;
|
|
|
|
if (PyArg_ParseTuple(args, (char*)"ss", &app, &obj)) {
|
|
|
|
TQCStringList methods = Client::instance()->dcop()->remoteFunctions(TTQCString(app), TTQCString(obj) );
|
|
|
|
return make_py_list(methods);
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
PyObject *register_as( PyObject */*self*/, PyObject *args) {
|
|
|
|
const char *appid;
|
|
|
|
int add_pid = 1;
|
|
|
|
if (PyArg_ParseTuple(args, (char*)"s|i", &appid, &add_pid)) {
|
|
|
|
TTQCString actual_appid = Client::instance()->dcop()->registerAs(TTQCString(appid), add_pid!=0);
|
|
|
|
return PyString_FromString(actual_appid.data());
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
PyObject *create_dcop_object( PyObject */*self*/, PyObject *args) {
|
|
|
|
PyObject *py_dcop_object;
|
|
|
|
const char *objid = NULL;
|
|
|
|
if (PyArg_ParseTuple(args, (char*)"O|s", &py_dcop_object, &objid)) {
|
|
|
|
Py_INCREF(py_dcop_object);
|
|
|
|
PCOPObject *obj = objid ? new PCOPObject(py_dcop_object, objid) : new PCOPObject(py_dcop_object);
|
|
|
|
return PyCObject_FromVoidPtr( (void*)obj, delete_dcop_object );
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* pcop.set_method_list( <dcopobject cobject>, <method list> )
|
|
|
|
* where <method list> is a list of tuples
|
|
|
|
* [ ('method signature', python method), ... ]
|
|
|
|
*/
|
|
|
|
PyObject *set_method_list( PyObject */*self*/, PyObject *args) {
|
|
|
|
PyObject *c_obj;
|
|
|
|
PyObject *method_list;
|
|
|
|
if (PyArg_ParseTuple(args, (char*)"OO", &c_obj, &method_list) &&
|
|
|
|
PyCObject_Check(c_obj) &&
|
|
|
|
PyList_Check(method_list)) {
|
|
|
|
|
|
|
|
// extract each tuple from the list, aborting if any is invalid
|
|
|
|
TTQAsciiDict<PyObject> meth_list;
|
|
|
|
int size = PyList_Size(method_list);
|
|
|
|
for(int c=0;c<size;c++) {
|
|
|
|
PyObject *tuple = PyList_GetItem(method_list,c);
|
|
|
|
const char *method_signature = NULL;
|
|
|
|
PyObject *py_method = NULL;
|
|
|
|
if (!PyArg_ParseTuple(tuple, (char*)"sO", &method_signature, &py_method))
|
|
|
|
return NULL;
|
|
|
|
Py_INCREF(py_method);
|
|
|
|
meth_list.insert(method_signature, py_method);
|
|
|
|
}
|
|
|
|
|
|
|
|
PCOPObject *obj = (PCOPObject*)PyCObject_AsVoidPtr(c_obj);
|
|
|
|
if (obj) {
|
|
|
|
if (!obj->setMethodList(meth_list)) return NULL;
|
|
|
|
}
|
|
|
|
Py_INCREF(Py_None);
|
|
|
|
return Py_None;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
PyObject *get_method_list(PyObject */*self*/, PyObject *args) {
|
|
|
|
PyObject *c_obj;
|
|
|
|
if (PyArg_ParseTuple(args, (char*)"O", &c_obj)) {
|
|
|
|
if (PyCObject_Check(c_obj)) {
|
|
|
|
PCOPObject *obj = (PCOPObject*)PyCObject_AsVoidPtr(c_obj);
|
|
|
|
return obj->methodList();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
PyObject *connect_DCOP_Signal( PyObject */*self*/, PyObject *args) {
|
|
|
|
const char *sender;
|
|
|
|
const char *senderObj;
|
|
|
|
const char *signal;
|
|
|
|
const char *receiverObj;
|
|
|
|
const char *slot;
|
|
|
|
|
|
|
|
int volint = 0;
|
|
|
|
if (PyArg_ParseTuple(args, (char*)"sssss|i", &sender, &senderObj, &signal, &receiverObj, &slot, &volint)) {
|
|
|
|
bool success = Client::instance()->dcop()->connectDCOPSignal(TTQCString(sender), TTQCString(senderObj), TTQCString(signal), TTQCString(receiverObj), TTQCString(slot), (volint == 1)?true:false);
|
|
|
|
return Py_BuildValue("i", success?1:0);
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
PyObject *disconnect_DCOP_Signal( PyObject *self, PyObject *args) {
|
|
|
|
const char *sender;
|
|
|
|
const char *senderObj;
|
|
|
|
const char *signal;
|
|
|
|
const char *receiverObj;
|
|
|
|
const char *slot;
|
|
|
|
|
|
|
|
if (PyArg_ParseTuple(args, (char*)"sssss", &sender, &senderObj, &signal, &receiverObj, &slot)) {
|
|
|
|
bool success = Client::instance()->dcop()->disconnectDCOPSignal(TTQCString(sender), TTQCString(senderObj), TTQCString(signal), TTQCString(receiverObj), TTQCString(slot));
|
|
|
|
return Py_BuildValue("i", success?1:0);
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void delete_dcop_object(void *vp) {
|
|
|
|
if (vp) {
|
|
|
|
PCOPObject *obj = (PCOPObject*)vp;
|
|
|
|
delete obj;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
PyObject *process_events( PyObject */*self*/, PyObject */*args*/) {
|
|
|
|
Client::instance()->processEvents();
|
|
|
|
Py_INCREF(Py_None);
|
|
|
|
return Py_None;
|
|
|
|
}
|
|
|
|
|
|
|
|
// helpers
|
|
|
|
|
|
|
|
PyObject *make_py_list( const TQCStringList &qt_list) {
|
|
|
|
PyObject *l = PyList_New(qt_list.count());
|
|
|
|
uint c=0;
|
|
|
|
for(TQCStringList::ConstIterator it = qt_list.begin();
|
|
|
|
it!=qt_list.end();
|
|
|
|
++it,c++)
|
|
|
|
PyList_SetItem(l, c, PyString_FromString( (*it).data() ) );
|
|
|
|
return l;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
PyMethodDef PCOPMethods[] = {
|
|
|
|
{ (char*)"dcop_call", PythonDCOP::dcop_call, METH_VARARGS, (char*)"Make a call to DCOP." },
|
|
|
|
{ (char*)"app_list", PythonDCOP::application_list, METH_VARARGS, (char*)"Return a list of DCOP registered application." },
|
|
|
|
{ (char*)"obj_list", PythonDCOP::object_list, METH_VARARGS, (char*)"Return a list of objects for a DCOP registered application."},
|
|
|
|
{ (char*)"method_list", PythonDCOP::method_list, METH_VARARGS, (char*)"Return a list of methods for a DCOP object."},
|
|
|
|
{ (char*)"register_as", PythonDCOP::register_as, METH_VARARGS, (char*)"Register the application with DCOP."},
|
|
|
|
{ (char*)"create_dcop_object", PythonDCOP::create_dcop_object, METH_VARARGS, (char*)"Creates a DCOP Object instance."},
|
|
|
|
{ (char*)"process_events", PythonDCOP::process_events, METH_VARARGS, (char*)"Processes QT events."},
|
|
|
|
{ (char*)"set_method_list", PythonDCOP::set_method_list, METH_VARARGS, (char*)"Set the list of methods for a DCOP server object."},
|
|
|
|
{ (char*)"connect_dcop_signal", PythonDCOP::connect_DCOP_Signal, METH_VARARGS, (char*)"Connect a dcop signal."},
|
|
|
|
{ (char*)"disconnect_dcop_signal", PythonDCOP::disconnect_DCOP_Signal, METH_VARARGS, (char*)"Disconnect a dcop signal."},
|
|
|
|
{ NULL, NULL, 0, NULL } /* Sentinel */
|
|
|
|
};
|
|
|
|
|
|
|
|
extern "C"
|
|
|
|
{
|
|
|
|
|
|
|
|
void initpcop()
|
|
|
|
{
|
|
|
|
(void) Py_InitModule( (char*)"pcop", PCOPMethods );
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|