|
|
|
/***************************************************************************
|
|
|
|
Korundum.cpp - Runtime for KDE services, DCOP etc
|
|
|
|
-------------------
|
|
|
|
begin : Sun Sep 28 2003
|
|
|
|
copyright : (C) 2003-2004 by Richard Dale
|
|
|
|
email : Richard_Dale@tipitina.demon.co.uk
|
|
|
|
***************************************************************************/
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
|
|
* *
|
|
|
|
* 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 <tqobject.h>
|
|
|
|
#include <tqstringlist.h>
|
|
|
|
#include <tqmap.h>
|
|
|
|
#include <tqdatastream.h>
|
|
|
|
|
|
|
|
#include <tdeversion.h>
|
|
|
|
#include <dcopclient.h>
|
|
|
|
#include <dcopobject.h>
|
|
|
|
#include <dcopref.h>
|
|
|
|
#include <kapplication.h>
|
|
|
|
#include <kurl.h>
|
|
|
|
#if TDE_VERSION >= 0x030200
|
|
|
|
#include <kconfigskeleton.h>
|
|
|
|
#endif
|
|
|
|
#include <kio/global.h>
|
|
|
|
#include <kparts/browserextension.h>
|
|
|
|
#include <kde_terminal_interface.h>
|
|
|
|
|
|
|
|
#include <ruby.h>
|
|
|
|
|
|
|
|
#include <marshall.h>
|
|
|
|
#include <qtruby.h>
|
|
|
|
#include <smokeruby.h>
|
|
|
|
#include <smoke.h>
|
|
|
|
|
|
|
|
extern "C" {
|
|
|
|
extern VALUE qt_internal_module;
|
|
|
|
extern VALUE kconfigskeleton_class;
|
|
|
|
extern VALUE kconfigskeleton_itemenum_choice_class;
|
|
|
|
extern VALUE kio_udsatom_class;
|
|
|
|
extern VALUE konsole_part_class;
|
|
|
|
extern VALUE set_obj_info(const char * className, smokeruby_object * o);
|
|
|
|
extern void set_kde_resolve_classname(const char * (*kde_resolve_classname) (Smoke*, int, void *));
|
|
|
|
extern const char * kde_resolve_classname(Smoke* smoke, int classId, void * ptr);
|
|
|
|
};
|
|
|
|
|
|
|
|
extern TypeHandler KDE_handlers[];
|
|
|
|
extern void install_handlers(TypeHandler *);
|
|
|
|
extern Smoke *qt_Smoke;
|
|
|
|
|
|
|
|
|
|
|
|
static VALUE kde_internal_module;
|
|
|
|
Marshall::HandlerFn getMarshallFn(const SmokeType &type);
|
|
|
|
|
|
|
|
/*
|
|
|
|
Copy items from the stack to the stream, each item has a corresponding description in the
|
|
|
|
args array of MocArguments. Used for marshalling the args to DCOP calls and sends, emitting
|
|
|
|
DCOP signals, and converting the return value of a DCOP slot to a stream.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
smokeStackToStream(Marshall *m, Smoke::Stack stack, TQDataStream* stream, int items, MocArgument* args)
|
|
|
|
{
|
|
|
|
for(int i = 0; i < items; i++) {
|
|
|
|
switch(args[i].argType) {
|
|
|
|
case xmoc_bool:
|
|
|
|
*stream << stack[i].s_bool;
|
|
|
|
break;
|
|
|
|
case xmoc_int:
|
|
|
|
*stream << stack[i].s_int;
|
|
|
|
break;
|
|
|
|
case xmoc_double:
|
|
|
|
*stream << stack[i].s_double;
|
|
|
|
break;
|
|
|
|
case xmoc_charstar:
|
|
|
|
*stream << (char *) stack[i].s_voidp;
|
|
|
|
break;
|
|
|
|
case xmoc_QString:
|
|
|
|
{
|
|
|
|
TQString temp((const TQString&) *((TQString *) stack[i].s_voidp));
|
|
|
|
*stream << temp;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
{
|
|
|
|
const SmokeType &t = args[i].st;
|
|
|
|
switch(t.elem()) {
|
|
|
|
case Smoke::t_bool:
|
|
|
|
*stream << stack[i].s_bool;
|
|
|
|
break;
|
|
|
|
case Smoke::t_char:
|
|
|
|
*stream << stack[i].s_char;
|
|
|
|
break;
|
|
|
|
case Smoke::t_uchar:
|
|
|
|
*stream << stack[i].s_uchar;
|
|
|
|
break;
|
|
|
|
case Smoke::t_short:
|
|
|
|
*stream << stack[i].s_short;
|
|
|
|
break;
|
|
|
|
case Smoke::t_ushort:
|
|
|
|
*stream << stack[i].s_ushort;
|
|
|
|
break;
|
|
|
|
case Smoke::t_int:
|
|
|
|
*stream << stack[i].s_int;
|
|
|
|
break;
|
|
|
|
case Smoke::t_uint:
|
|
|
|
*stream << stack[i].s_uint;
|
|
|
|
break;
|
|
|
|
case Smoke::t_long:
|
|
|
|
*stream << stack[i].s_long;
|
|
|
|
break;
|
|
|
|
case Smoke::t_ulong:
|
|
|
|
*stream << stack[i].s_ulong;
|
|
|
|
break;
|
|
|
|
case Smoke::t_float:
|
|
|
|
*stream << stack[i].s_float;
|
|
|
|
break;
|
|
|
|
case Smoke::t_double:
|
|
|
|
*stream << stack[i].s_double;
|
|
|
|
break;
|
|
|
|
case Smoke::t_enum:
|
|
|
|
m->unsupported();
|
|
|
|
break;
|
|
|
|
case Smoke::t_class:
|
|
|
|
case Smoke::t_voidp:
|
|
|
|
{
|
|
|
|
// Special case any types which are in the Smoke runtime, but
|
|
|
|
// don't have TQDataStream '<<' methods
|
|
|
|
if (strcmp(t.name(), "TQCString") == 0) {
|
|
|
|
TQCString temp((const TQCString&) *((TQCString *) stack[i].s_voidp));
|
|
|
|
*stream << temp;
|
|
|
|
break;
|
|
|
|
} else if (strcmp(t.name(), "QCStringList") == 0) {
|
|
|
|
QCStringList temp((const QCStringList&) *((QCStringList *) stack[i].s_voidp));
|
|
|
|
*stream << temp;
|
|
|
|
break;
|
|
|
|
} else if (strcmp(t.name(), "TQStringList") == 0) {
|
|
|
|
TQStringList temp((const TQStringList&) *((TQStringList *) stack[i].s_voidp));
|
|
|
|
*stream << temp;
|
|
|
|
break;
|
|
|
|
} else if (strcmp(t.name(), "KURL::List") == 0) {
|
|
|
|
KURL::List temp((const KURL::List&) *((KURL::List *) stack[i].s_voidp));
|
|
|
|
*stream << temp;
|
|
|
|
break;
|
|
|
|
} else if (strcmp(t.name(), "TQMap<TQCString,DCOPRef>") == 0) {
|
|
|
|
TQMap<TQCString,DCOPRef> temp((const TQMap<TQCString,DCOPRef>&) *((TQMap<TQCString,DCOPRef>*) stack[i].s_voidp));
|
|
|
|
*stream << temp;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Look for methods of the form: TQDataStream & operator<<(TQDataStream&, const MyClass&)
|
|
|
|
Smoke::Index meth = t.smoke()->findMethod("TQGlobalSpace", "operator<<##");
|
|
|
|
Smoke::Index ix;
|
|
|
|
if (meth > 0) {
|
|
|
|
ix = t.smoke()->methodMaps[meth].method;
|
|
|
|
ix = -ix; // turn into ambiguousMethodList index
|
|
|
|
while (t.smoke()->ambiguousMethodList[ix]) {
|
|
|
|
Smoke::Method &method = t.smoke()->methods[t.smoke()->ambiguousMethodList[ix]];
|
|
|
|
TQString refType("const ");
|
|
|
|
refType += t.name();
|
|
|
|
refType += "&";
|
|
|
|
if ( strcmp( "TQDataStream&",
|
|
|
|
t.smoke()->types[t.smoke()->argumentList[method.args+0]].name ) == 0
|
|
|
|
&& strcmp( refType.latin1(),
|
|
|
|
t.smoke()->types[t.smoke()->argumentList[method.args+1]].name ) == 0 )
|
|
|
|
{
|
|
|
|
Smoke::ClassFn fn = t.smoke()->classes[method.classId].classFn;
|
|
|
|
Smoke::StackItem local_stack[3];
|
|
|
|
local_stack[1].s_voidp = stream;
|
|
|
|
local_stack[2].s_voidp = stack[i].s_voidp;
|
|
|
|
// Call the TQDataStream marshaller write method
|
|
|
|
// with the instance to be marshalled
|
|
|
|
(*fn)(method.method, 0, local_stack);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
ix++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Copy items from the stream to the stack, each item has a corresponding description in the
|
|
|
|
args array of MocArguments. Used for marshalling the arguments to a DCOP slot invocation,
|
|
|
|
and for converting a dcop reply to a ruby value.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
smokeStackFromStream(Marshall *m, Smoke::Stack stack, TQDataStream* stream, int items, MocArgument* args)
|
|
|
|
{
|
|
|
|
for(int i = 0; i < items; i++) {
|
|
|
|
switch(args[i].argType) {
|
|
|
|
case xmoc_bool:
|
|
|
|
{
|
|
|
|
*stream >> stack[i].s_bool;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case xmoc_int:
|
|
|
|
{
|
|
|
|
*stream >> stack[i].s_int;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case xmoc_double:
|
|
|
|
*stream >> stack[i].s_double;
|
|
|
|
break;
|
|
|
|
case xmoc_charstar:
|
|
|
|
*stream >> (char *&) stack[i].s_voidp;
|
|
|
|
break;
|
|
|
|
case xmoc_QString:
|
|
|
|
{
|
|
|
|
TQString temp;
|
|
|
|
*stream >> temp;
|
|
|
|
stack[i].s_voidp = new TQString(temp);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default: // case xmoc_ptr:
|
|
|
|
{
|
|
|
|
const SmokeType &t = args[i].st;
|
|
|
|
switch(t.elem()) {
|
|
|
|
case Smoke::t_bool:
|
|
|
|
{
|
|
|
|
*stream >> stack[i].s_bool;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case Smoke::t_char:
|
|
|
|
{
|
|
|
|
*stream >> stack[i].s_char;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case Smoke::t_uchar:
|
|
|
|
{
|
|
|
|
*stream >> stack[i].s_uchar;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case Smoke::t_short:
|
|
|
|
{
|
|
|
|
*stream >> stack[i].s_short;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case Smoke::t_ushort:
|
|
|
|
{
|
|
|
|
*stream >> stack[i].s_ushort;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case Smoke::t_int:
|
|
|
|
{
|
|
|
|
*stream >> stack[i].s_int;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case Smoke::t_uint:
|
|
|
|
{
|
|
|
|
*stream >> stack[i].s_uint;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case Smoke::t_long:
|
|
|
|
{
|
|
|
|
*stream >> stack[i].s_long;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case Smoke::t_ulong:
|
|
|
|
{
|
|
|
|
*stream >> stack[i].s_ulong;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case Smoke::t_float:
|
|
|
|
*stream >> stack[i].s_float;
|
|
|
|
break;
|
|
|
|
case Smoke::t_double:
|
|
|
|
*stream >> stack[i].s_double;
|
|
|
|
break;
|
|
|
|
case Smoke::t_enum:
|
|
|
|
m->unsupported();
|
|
|
|
break;
|
|
|
|
case Smoke::t_class:
|
|
|
|
case Smoke::t_voidp:
|
|
|
|
{
|
|
|
|
// Special case any types which are in the Smoke runtime, but
|
|
|
|
// don't have TQDataStream '>>' methods
|
|
|
|
if (strcmp(t.name(), "TQCString") == 0) {
|
|
|
|
TQCString temp;
|
|
|
|
*stream >> temp;
|
|
|
|
stack[i].s_voidp = new TQCString(temp);
|
|
|
|
break;
|
|
|
|
} else if (strcmp(t.name(), "QCStringList") == 0) {
|
|
|
|
QCStringList temp;
|
|
|
|
*stream >> temp;
|
|
|
|
stack[i].s_voidp = new QCStringList(temp);
|
|
|
|
break;
|
|
|
|
} else if (strcmp(t.name(), "TQStringList") == 0) {
|
|
|
|
TQStringList temp;
|
|
|
|
*stream >> temp;
|
|
|
|
stack[i].s_voidp = new TQStringList(temp);
|
|
|
|
break;
|
|
|
|
} else if (strcmp(t.name(), "KURL::List") == 0) {
|
|
|
|
KURL::List temp;
|
|
|
|
*stream >> temp;
|
|
|
|
stack[i].s_voidp = new KURL::List(temp);
|
|
|
|
break;
|
|
|
|
} else if (strcmp(t.name(), "TQMap<TQCString,DCOPRef>") == 0) {
|
|
|
|
TQMap<TQCString,DCOPRef> temp;
|
|
|
|
*stream >> temp;
|
|
|
|
stack[i].s_voidp = new TQMap<TQCString,DCOPRef>(temp);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// First construct an instance to read the TQDataStream into,
|
|
|
|
// so look for a no args constructor
|
|
|
|
Smoke::Index ctorId = t.smoke()->idMethodName(t.name());
|
|
|
|
Smoke::Index ctorMeth = t.smoke()->findMethod(t.classId(), ctorId);
|
|
|
|
Smoke::Index ctor = t.smoke()->methodMaps[ctorMeth].method;
|
|
|
|
if(ctor < 1) {
|
|
|
|
stack[i].s_voidp = 0;
|
|
|
|
m->unsupported();
|
|
|
|
break; // Ambiguous or non-existent method, shouldn't happen with a no arg constructor
|
|
|
|
}
|
|
|
|
// Okay, ctor is the constructor. Time to call it.
|
|
|
|
Smoke::StackItem ctor_stack[1];
|
|
|
|
ctor_stack[0].s_voidp = 0;
|
|
|
|
Smoke::ClassFn classfn = t.smoke()->classes[t.classId()].classFn;
|
|
|
|
(*classfn)(t.smoke()->methods[ctor].method, 0, ctor_stack);
|
|
|
|
stack[i].s_voidp = ctor_stack[0].s_voidp;
|
|
|
|
|
|
|
|
// Look for methods of the form: TQDataStream & operator>>(TQDataStream&, MyClass&)
|
|
|
|
Smoke::Index meth = t.smoke()->findMethod("TQGlobalSpace", "operator>>##");
|
|
|
|
Smoke::Index ix;
|
|
|
|
if (meth > 0) {
|
|
|
|
ix = t.smoke()->methodMaps[meth].method;
|
|
|
|
ix = -ix; // turn into ambiguousMethodList index
|
|
|
|
while (t.smoke()->ambiguousMethodList[ix]) {
|
|
|
|
Smoke::Method &method = t.smoke()->methods[t.smoke()->ambiguousMethodList[ix]];
|
|
|
|
TQString refType(t.name());
|
|
|
|
refType += "&";
|
|
|
|
if ( strcmp( "TQDataStream&",
|
|
|
|
t.smoke()->types[t.smoke()->argumentList[method.args+0]].name ) == 0
|
|
|
|
&& strcmp( refType.latin1(),
|
|
|
|
t.smoke()->types[t.smoke()->argumentList[method.args+1]].name ) == 0 )
|
|
|
|
{
|
|
|
|
Smoke::ClassFn fn = t.smoke()->classes[method.classId].classFn;
|
|
|
|
Smoke::StackItem local_stack[3];
|
|
|
|
local_stack[1].s_voidp = stream;
|
|
|
|
local_stack[2].s_voidp = stack[i].s_voidp;
|
|
|
|
// Call the TQDataStream marshaller read method
|
|
|
|
// on the instance to be marshalled
|
|
|
|
(*fn)(method.method, 0, local_stack);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
ix++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Converts a TQByteArray returned from a DCOP call to a ruby value.
|
|
|
|
*/
|
|
|
|
class DCOPReturn : public Marshall {
|
|
|
|
MocArgument * _replyType;
|
|
|
|
Smoke::Stack _stack;
|
|
|
|
VALUE * _result;
|
|
|
|
public:
|
|
|
|
DCOPReturn(TQDataStream & retval, VALUE * result, VALUE replyType)
|
|
|
|
{
|
|
|
|
_result = result;
|
|
|
|
VALUE temp = rb_funcall(qt_internal_module, rb_intern("getMocArguments"), 1, replyType);
|
|
|
|
Data_Get_Struct(rb_ary_entry(temp, 1), MocArgument, _replyType);
|
|
|
|
_stack = new Smoke::StackItem[1];
|
|
|
|
smokeStackFromStream(this, _stack, &retval, 1, _replyType);
|
|
|
|
Marshall::HandlerFn fn = getMarshallFn(type());
|
|
|
|
(*fn)(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
SmokeType type() {
|
|
|
|
return _replyType[0].st;
|
|
|
|
}
|
|
|
|
Marshall::Action action() { return Marshall::ToVALUE; }
|
|
|
|
Smoke::StackItem &item() { return _stack[0]; }
|
|
|
|
VALUE * var() {
|
|
|
|
return _result;
|
|
|
|
}
|
|
|
|
|
|
|
|
void unsupported()
|
|
|
|
{
|
|
|
|
rb_raise(rb_eArgError, "Cannot handle '%s' as DCOP return-type", type().name());
|
|
|
|
}
|
|
|
|
Smoke *smoke() { return type().smoke(); }
|
|
|
|
|
|
|
|
void next() {}
|
|
|
|
|
|
|
|
bool cleanup() { return false; }
|
|
|
|
|
|
|
|
~DCOPReturn()
|
|
|
|
{
|
|
|
|
delete[] _stack;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class DCOPCall : public Marshall {
|
|
|
|
VALUE _obj;
|
|
|
|
TQCString & _remFun;
|
|
|
|
int _items;
|
|
|
|
VALUE *_sp;
|
|
|
|
TQByteArray *_data;
|
|
|
|
TQDataStream *_stream;
|
|
|
|
int _id;
|
|
|
|
MocArgument *_args;
|
|
|
|
bool _useEventLoop;
|
|
|
|
int _timeout;
|
|
|
|
int _cur;
|
|
|
|
Smoke::Stack _stack;
|
|
|
|
VALUE _result;
|
|
|
|
bool _called;
|
|
|
|
public:
|
|
|
|
DCOPCall(VALUE obj, TQCString & remFun, int items, VALUE *sp, VALUE args, bool useEventLoop, int timeout) :
|
|
|
|
_obj(obj), _remFun(remFun), _items(items), _sp(sp),
|
|
|
|
_useEventLoop(useEventLoop), _timeout(timeout), _cur(-1), _called(false)
|
|
|
|
{
|
|
|
|
_data = new TQByteArray();
|
|
|
|
_stream = new TQDataStream(*_data, IO_WriteOnly);
|
|
|
|
Data_Get_Struct(rb_ary_entry(args, 1), MocArgument, _args);
|
|
|
|
_stack = new Smoke::StackItem[_items];
|
|
|
|
_result = Qnil;
|
|
|
|
}
|
|
|
|
|
|
|
|
~DCOPCall()
|
|
|
|
{
|
|
|
|
delete[] _stack;
|
|
|
|
delete _data;
|
|
|
|
delete _stream;
|
|
|
|
}
|
|
|
|
const MocArgument &arg() { return _args[_cur]; }
|
|
|
|
SmokeType type() { return arg().st; }
|
|
|
|
Marshall::Action action() { return Marshall::FromVALUE; }
|
|
|
|
Smoke::StackItem &item() { return _stack[_cur]; }
|
|
|
|
VALUE * var() {
|
|
|
|
if(_cur < 0) return &_result;
|
|
|
|
return _sp + _cur;
|
|
|
|
}
|
|
|
|
|
|
|
|
void unsupported()
|
|
|
|
{
|
|
|
|
rb_raise(rb_eArgError, "Cannot handle '%s' as a DCOP call argument", type().name());
|
|
|
|
}
|
|
|
|
|
|
|
|
Smoke *smoke() { return type().smoke(); }
|
|
|
|
|
|
|
|
void dcopCall()
|
|
|
|
{
|
|
|
|
if(_called) return;
|
|
|
|
_called = true;
|
|
|
|
|
|
|
|
smokeStackToStream(this, _stack, _stream, _items, _args);
|
|
|
|
smokeruby_object *o = value_obj_info(_obj);
|
|
|
|
DCOPRef * dcopRef = (DCOPRef *) o->smoke->cast(o->ptr, o->classId, o->smoke->idClass("DCOPRef"));
|
|
|
|
DCOPClient* dc = dcopRef->dcopClient();
|
|
|
|
TQCString replyType;
|
|
|
|
TQByteArray dataReceived;
|
|
|
|
#if TDE_VERSION >= 0x030200
|
|
|
|
bool ok = dc->call(dcopRef->app(), dcopRef->obj(), _remFun, *_data, replyType, dataReceived, _useEventLoop, _timeout);
|
|
|
|
#else
|
|
|
|
bool ok = dc->call(dcopRef->app(), dcopRef->obj(), _remFun, *_data, replyType, dataReceived, _useEventLoop);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (!ok) {
|
|
|
|
// Note that a failed dcop call returns 'nil', not 'false'
|
|
|
|
_result = Qnil;
|
|
|
|
return;
|
|
|
|
} else if (replyType == "void" || replyType == "ASYNC") {
|
|
|
|
_result = Qtrue;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQDataStream ds(dataReceived, IO_ReadOnly);
|
|
|
|
|
|
|
|
if (replyType == "TQValueList<DCOPRef>") {
|
|
|
|
// Special case TQValueList<DCOPRef> as a TQDataStream marshaller
|
|
|
|
// isn't in the Smoke runtime
|
|
|
|
TQValueList<DCOPRef> valuelist;
|
|
|
|
ds >> valuelist;
|
|
|
|
_result = rb_ary_new();
|
|
|
|
for (TQValueListIterator<DCOPRef> it = valuelist.begin(); it != valuelist.end(); ++it) {
|
|
|
|
void *p = new DCOPRef(*it);
|
|
|
|
VALUE obj = getPointerObject(p);
|
|
|
|
|
|
|
|
if (obj == Qnil) {
|
|
|
|
smokeruby_object * o = ALLOC(smokeruby_object);
|
|
|
|
o->classId = qt_Smoke->idClass("DCOPRef");
|
|
|
|
o->smoke = qt_Smoke;
|
|
|
|
o->ptr = p;
|
|
|
|
o->allocated = true;
|
|
|
|
obj = set_obj_info("KDE::DCOPRef", o);
|
|
|
|
}
|
|
|
|
|
|
|
|
rb_ary_push(_result, obj);
|
|
|
|
}
|
|
|
|
} else if (replyType == "TQValueList<TQCString>") {
|
|
|
|
// And special case this type too
|
|
|
|
TQValueList<TQCString> propertyList;
|
|
|
|
ds >> propertyList;
|
|
|
|
_result = rb_ary_new();
|
|
|
|
for (TQValueListIterator<TQCString> it = propertyList.begin(); it != propertyList.end(); ++it) {
|
|
|
|
rb_ary_push(_result, rb_str_new2((const char *) *it));
|
|
|
|
}
|
|
|
|
} else if (replyType == "TQValueList<int>") {
|
|
|
|
// And special case this type too
|
|
|
|
TQValueList<int> propertyList;
|
|
|
|
ds >> propertyList;
|
|
|
|
_result = rb_ary_new();
|
|
|
|
for (TQValueListIterator<int> it = propertyList.begin(); it != propertyList.end(); ++it) {
|
|
|
|
rb_ary_push(_result, INT2NUM(*it));
|
|
|
|
}
|
|
|
|
} else if (replyType == "TQMap<TQString,DCOPRef>") {
|
|
|
|
// And another..
|
|
|
|
TQMap<TQString,DCOPRef> actionMap;
|
|
|
|
ds >> actionMap;
|
|
|
|
_result = rb_hash_new();
|
|
|
|
|
|
|
|
TQMap<TQString,DCOPRef>::Iterator it;
|
|
|
|
for (it = actionMap.begin(); it != actionMap.end(); ++it) {
|
|
|
|
void *p = new DCOPRef(it.data());
|
|
|
|
VALUE obj = getPointerObject(p);
|
|
|
|
|
|
|
|
if (obj == Qnil) {
|
|
|
|
smokeruby_object * o = ALLOC(smokeruby_object);
|
|
|
|
o->classId = qt_Smoke->idClass("DCOPRef");
|
|
|
|
o->smoke = qt_Smoke;
|
|
|
|
o->ptr = p;
|
|
|
|
o->allocated = true;
|
|
|
|
obj = set_obj_info("KDE::DCOPRef", o);
|
|
|
|
}
|
|
|
|
|
|
|
|
rb_hash_aset(_result, rb_str_new2(it.key().latin1()), obj);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
DCOPReturn dcopReturn(ds, &_result, rb_str_new2((const char *) replyType));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void next()
|
|
|
|
{
|
|
|
|
int oldcur = _cur;
|
|
|
|
_cur++;
|
|
|
|
|
|
|
|
while(!_called && _cur < _items) {
|
|
|
|
Marshall::HandlerFn fn = getMarshallFn(type());
|
|
|
|
(*fn)(this);
|
|
|
|
_cur++;
|
|
|
|
}
|
|
|
|
|
|
|
|
dcopCall();
|
|
|
|
_cur = oldcur;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool cleanup() { return true; }
|
|
|
|
};
|
|
|
|
|
|
|
|
class DCOPSend : public Marshall {
|
|
|
|
VALUE _obj;
|
|
|
|
TQCString & _remFun;
|
|
|
|
TQByteArray *_data;
|
|
|
|
TQDataStream *_stream;
|
|
|
|
int _id;
|
|
|
|
MocArgument *_args;
|
|
|
|
int _items;
|
|
|
|
VALUE *_sp;
|
|
|
|
int _cur;
|
|
|
|
VALUE * _result;
|
|
|
|
Smoke::Stack _stack;
|
|
|
|
bool _called;
|
|
|
|
public:
|
|
|
|
DCOPSend(VALUE obj, TQCString & remFun, int items, VALUE *sp, VALUE args, VALUE * result) :
|
|
|
|
_obj(obj), _remFun(remFun), _items(items), _sp(sp), _cur(-1), _result(result), _called(false)
|
|
|
|
{
|
|
|
|
_data = new TQByteArray();
|
|
|
|
_stream = new TQDataStream(*_data, IO_WriteOnly);
|
|
|
|
Data_Get_Struct(rb_ary_entry(args, 1), MocArgument, _args);
|
|
|
|
_stack = new Smoke::StackItem[_items];
|
|
|
|
}
|
|
|
|
|
|
|
|
~DCOPSend()
|
|
|
|
{
|
|
|
|
delete[] _stack;
|
|
|
|
delete _data;
|
|
|
|
delete _stream;
|
|
|
|
}
|
|
|
|
const MocArgument &arg() { return _args[_cur]; }
|
|
|
|
SmokeType type() { return arg().st; }
|
|
|
|
Marshall::Action action() { return Marshall::FromVALUE; }
|
|
|
|
Smoke::StackItem &item() { return _stack[_cur]; }
|
|
|
|
VALUE * var() { return _sp + _cur; }
|
|
|
|
|
|
|
|
void unsupported()
|
|
|
|
{
|
|
|
|
rb_raise(rb_eArgError, "Cannot handle '%s' as a DCOP send argument", type().name());
|
|
|
|
}
|
|
|
|
|
|
|
|
Smoke *smoke() { return type().smoke(); }
|
|
|
|
|
|
|
|
void dcopSend()
|
|
|
|
{
|
|
|
|
if(_called) return;
|
|
|
|
_called = true;
|
|
|
|
|
|
|
|
smokeStackToStream(this, _stack, _stream, _items, _args);
|
|
|
|
smokeruby_object *o = value_obj_info(_obj);
|
|
|
|
DCOPRef * dcopRef = (DCOPRef *) o->smoke->cast(o->ptr, o->classId, o->smoke->idClass("DCOPRef"));
|
|
|
|
DCOPClient* dc = dcopRef->dcopClient();
|
|
|
|
bool ok = dc->send(dcopRef->app(), dcopRef->obj(), _remFun, *_data);
|
|
|
|
*_result = (ok ? Qtrue : Qfalse);
|
|
|
|
}
|
|
|
|
|
|
|
|
void next()
|
|
|
|
{
|
|
|
|
int oldcur = _cur;
|
|
|
|
_cur++;
|
|
|
|
|
|
|
|
while(!_called && _cur < _items) {
|
|
|
|
Marshall::HandlerFn fn = getMarshallFn(type());
|
|
|
|
(*fn)(this);
|
|
|
|
_cur++;
|
|
|
|
}
|
|
|
|
|
|
|
|
dcopSend();
|
|
|
|
_cur = oldcur;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool cleanup() { return true; }
|
|
|
|
};
|
|
|
|
|
|
|
|
class EmitDCOPSignal : public Marshall {
|
|
|
|
VALUE _obj;
|
|
|
|
const char * _signalName;
|
|
|
|
TQByteArray *_data;
|
|
|
|
TQDataStream *_stream;
|
|
|
|
int _id;
|
|
|
|
MocArgument *_args;
|
|
|
|
VALUE *_sp;
|
|
|
|
int _items;
|
|
|
|
int _cur;
|
|
|
|
Smoke::Stack _stack;
|
|
|
|
bool _called;
|
|
|
|
public:
|
|
|
|
EmitDCOPSignal(VALUE obj, const char * signalName, int items, VALUE *sp, VALUE args) :
|
|
|
|
_obj(obj), _signalName(signalName), _sp(sp), _items(items), _cur(-1), _called(false)
|
|
|
|
{
|
|
|
|
_data = new TQByteArray();
|
|
|
|
_stream = new TQDataStream(*_data, IO_WriteOnly);
|
|
|
|
Data_Get_Struct(rb_ary_entry(args, 1), MocArgument, _args);
|
|
|
|
_stack = new Smoke::StackItem[_items];
|
|
|
|
}
|
|
|
|
|
|
|
|
~EmitDCOPSignal()
|
|
|
|
{
|
|
|
|
delete[] _stack;
|
|
|
|
delete _stream;
|
|
|
|
delete _data;
|
|
|
|
}
|
|
|
|
const MocArgument &arg() { return _args[_cur]; }
|
|
|
|
SmokeType type() { return arg().st; }
|
|
|
|
Marshall::Action action() { return Marshall::FromVALUE; }
|
|
|
|
Smoke::StackItem &item() { return _stack[_cur]; }
|
|
|
|
VALUE * var() { return _sp + _cur; }
|
|
|
|
|
|
|
|
void unsupported()
|
|
|
|
{
|
|
|
|
rb_raise(rb_eArgError, "Cannot handle '%s' as a DCOP signal argument", type().name());
|
|
|
|
}
|
|
|
|
|
|
|
|
Smoke *smoke() { return type().smoke(); }
|
|
|
|
|
|
|
|
void emitSignal()
|
|
|
|
{
|
|
|
|
if(_called) return;
|
|
|
|
_called = true;
|
|
|
|
|
|
|
|
smokeStackToStream(this, _stack, _stream, _items, _args);
|
|
|
|
smokeruby_object *o = value_obj_info(_obj);
|
|
|
|
DCOPObject * dcopObject = (DCOPObject *) o->smoke->cast(o->ptr, o->classId, o->smoke->idClass("DCOPObject"));
|
|
|
|
dcopObject->emitDCOPSignal(_signalName, *_data);
|
|
|
|
}
|
|
|
|
|
|
|
|
void next()
|
|
|
|
{
|
|
|
|
int oldcur = _cur;
|
|
|
|
_cur++;
|
|
|
|
|
|
|
|
while(!_called && _cur < _items) {
|
|
|
|
Marshall::HandlerFn fn = getMarshallFn(type());
|
|
|
|
(*fn)(this);
|
|
|
|
_cur++;
|
|
|
|
}
|
|
|
|
|
|
|
|
emitSignal();
|
|
|
|
_cur = oldcur;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool cleanup() { return true; }
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
Converts a ruby value returned by a DCOP slot invocation to a TQByteArray
|
|
|
|
*/
|
|
|
|
class DCOPReplyValue : public Marshall {
|
|
|
|
MocArgument * _replyType;
|
|
|
|
Smoke::Stack _stack;
|
|
|
|
VALUE * _result;
|
|
|
|
public:
|
|
|
|
DCOPReplyValue(TQByteArray & retval, VALUE * result, VALUE replyType)
|
|
|
|
{
|
|
|
|
TQDataStream _retval(retval, IO_WriteOnly);
|
|
|
|
_result = result;
|
|
|
|
Data_Get_Struct(rb_ary_entry(replyType, 1), MocArgument, _replyType);
|
|
|
|
_stack = new Smoke::StackItem[1];
|
|
|
|
Marshall::HandlerFn fn = getMarshallFn(type());
|
|
|
|
(*fn)(this);
|
|
|
|
smokeStackToStream(this, _stack, &_retval, 1, _replyType);
|
|
|
|
}
|
|
|
|
|
|
|
|
SmokeType type() {
|
|
|
|
return _replyType[0].st;
|
|
|
|
}
|
|
|
|
Marshall::Action action() { return Marshall::FromVALUE; }
|
|
|
|
Smoke::StackItem &item() { return _stack[0]; }
|
|
|
|
VALUE * var() {
|
|
|
|
return _result;
|
|
|
|
}
|
|
|
|
|
|
|
|
void unsupported()
|
|
|
|
{
|
|
|
|
rb_raise(rb_eArgError, "Cannot handle '%s' as DCOP reply-type", type().name());
|
|
|
|
}
|
|
|
|
Smoke *smoke() { return type().smoke(); }
|
|
|
|
|
|
|
|
void next() {}
|
|
|
|
|
|
|
|
bool cleanup() { return false; }
|
|
|
|
|
|
|
|
~DCOPReplyValue() {
|
|
|
|
delete[] _stack;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class InvokeDCOPSlot : public Marshall {
|
|
|
|
VALUE _obj;
|
|
|
|
ID _slotname;
|
|
|
|
int _items;
|
|
|
|
MocArgument * _args;
|
|
|
|
TQDataStream * _stream;
|
|
|
|
const char * _replyTypeName;
|
|
|
|
VALUE _replyType;
|
|
|
|
TQByteArray * _retval;
|
|
|
|
int _cur;
|
|
|
|
bool _called;
|
|
|
|
VALUE * _sp;
|
|
|
|
Smoke::Stack _stack;
|
|
|
|
public:
|
|
|
|
const MocArgument &arg() { return _args[_cur]; }
|
|
|
|
SmokeType type() { return arg().st; }
|
|
|
|
Marshall::Action action() { return Marshall::ToVALUE; }
|
|
|
|
Smoke::StackItem &item() { return _stack[_cur]; }
|
|
|
|
VALUE * var() { return _sp + _cur; }
|
|
|
|
Smoke *smoke() { return type().smoke(); }
|
|
|
|
bool cleanup() { return false; }
|
|
|
|
|
|
|
|
void unsupported()
|
|
|
|
{
|
|
|
|
rb_raise(rb_eArgError, "Cannot handle '%s' as DCOP slot argument\n", type().name());
|
|
|
|
}
|
|
|
|
|
|
|
|
void copyArguments()
|
|
|
|
{
|
|
|
|
smokeStackFromStream(this, _stack, _stream, _items, _args);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
void invokeSlot()
|
|
|
|
{
|
|
|
|
if (_called) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
_called = true;
|
|
|
|
VALUE result = rb_funcall2(_obj, _slotname, _items, _sp);
|
|
|
|
|
|
|
|
if ( strcmp(_replyTypeName, "TQValueList<DCOPRef>") == 0
|
|
|
|
&& TYPE(result) == T_ARRAY )
|
|
|
|
{
|
|
|
|
// Special case TQValueList<DCOPRef> as a TQDataStream marshaller
|
|
|
|
// isn't in the Smoke runtime
|
|
|
|
TQValueList<DCOPRef> windowList;
|
|
|
|
|
|
|
|
for (long i = 0; i < RARRAY(result)->len; i++) {
|
|
|
|
VALUE item = rb_ary_entry(result, i);
|
|
|
|
smokeruby_object *o = value_obj_info(item);
|
|
|
|
if( !o || !o->ptr)
|
|
|
|
continue;
|
|
|
|
void * ptr = o->ptr;
|
|
|
|
ptr = o->smoke->cast(ptr, o->classId, o->smoke->idClass("DCOPRef"));
|
|
|
|
windowList.append((DCOPRef)*(DCOPRef*)ptr);
|
|
|
|
}
|
|
|
|
TQDataStream retval(*_retval, IO_WriteOnly);
|
|
|
|
retval << windowList;
|
|
|
|
} else if ( strcmp(_replyTypeName, "TQValueList<TQCString>") == 0
|
|
|
|
&& TYPE(result) == T_ARRAY )
|
|
|
|
{
|
|
|
|
// And special case this type too
|
|
|
|
TQValueList<TQCString> propertyList;
|
|
|
|
|
|
|
|
for (long i = 0; i < RARRAY(result)->len; i++) {
|
|
|
|
VALUE item = rb_ary_entry(result, i);
|
|
|
|
propertyList.append(TQCString(StringValuePtr(item)));
|
|
|
|
}
|
|
|
|
TQDataStream retval(*_retval, IO_WriteOnly);
|
|
|
|
retval << propertyList;
|
|
|
|
} else if ( strcmp(_replyTypeName, "TQMap<TQString,DCOPRef>") == 0
|
|
|
|
&& TYPE(result) == T_HASH )
|
|
|
|
{
|
|
|
|
// And another..
|
|
|
|
TQMap<TQString,DCOPRef> actionMap;
|
|
|
|
// Convert the ruby hash to an array of key/value arrays
|
|
|
|
VALUE temp = rb_funcall(result, rb_intern("to_a"), 0);
|
|
|
|
|
|
|
|
for (long i = 0; i < RARRAY(temp)->len; i++) {
|
|
|
|
VALUE action = rb_ary_entry(rb_ary_entry(temp, i), 0);
|
|
|
|
VALUE item = rb_ary_entry(rb_ary_entry(temp, i), 1);
|
|
|
|
|
|
|
|
smokeruby_object *o = value_obj_info(item);
|
|
|
|
if( !o || !o->ptr)
|
|
|
|
continue;
|
|
|
|
void * ptr = o->ptr;
|
|
|
|
ptr = o->smoke->cast(ptr, o->classId, o->smoke->idClass("DCOPRef"));
|
|
|
|
|
|
|
|
actionMap[TQString(StringValuePtr(action))] = (DCOPRef)*(DCOPRef*)ptr;
|
|
|
|
}
|
|
|
|
TQDataStream retval(*_retval, IO_WriteOnly);
|
|
|
|
retval << actionMap;
|
|
|
|
} else if (_replyType != Qnil) {
|
|
|
|
DCOPReplyValue dcopReply(*_retval, &result, _replyType);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void next()
|
|
|
|
{
|
|
|
|
int oldcur = _cur;
|
|
|
|
_cur++;
|
|
|
|
|
|
|
|
while(!_called && _cur < _items) {
|
|
|
|
Marshall::HandlerFn fn = getMarshallFn(type());
|
|
|
|
(*fn)(this);
|
|
|
|
_cur++;
|
|
|
|
}
|
|
|
|
|
|
|
|
invokeSlot();
|
|
|
|
_cur = oldcur;
|
|
|
|
}
|
|
|
|
|
|
|
|
InvokeDCOPSlot(VALUE obj, ID slotname, VALUE args, TQByteArray& data, VALUE replyTypeName, VALUE replyType, TQByteArray& returnValue) :
|
|
|
|
_obj(obj), _slotname(slotname), _replyType(replyType), _cur(-1), _called(false)
|
|
|
|
{
|
|
|
|
_replyTypeName = StringValuePtr(replyTypeName);
|
|
|
|
_items = NUM2INT(rb_ary_entry(args, 0));
|
|
|
|
_stream = new TQDataStream(data, IO_ReadOnly);
|
|
|
|
_retval = &returnValue;
|
|
|
|
|
|
|
|
Data_Get_Struct(rb_ary_entry(args, 1), MocArgument, _args);
|
|
|
|
_sp = ALLOC_N(VALUE, _items);
|
|
|
|
_stack = new Smoke::StackItem[_items];
|
|
|
|
|
|
|
|
copyArguments();
|
|
|
|
}
|
|
|
|
|
|
|
|
~InvokeDCOPSlot() {
|
|
|
|
delete[] _stack;
|
|
|
|
delete _stream;
|
|
|
|
for(int i=0;i<_items;++i) {
|
|
|
|
free(_sp++);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
extern "C" {
|
|
|
|
extern void Init_qtruby();
|
|
|
|
extern void set_new_kde(VALUE (*new_kde) (int, VALUE *, VALUE));
|
|
|
|
extern void set_kconfigskeletonitem_immutable(VALUE (*kconfigskeletonitem_immutable) (VALUE));
|
|
|
|
extern void set_kde_resolve_classname(const char * (*kde_resolve_classname) (Smoke*, int, void *));
|
|
|
|
extern const char * kde_resolve_classname(Smoke* smoke, int classId, void * ptr);
|
|
|
|
extern VALUE new_qt(int argc, VALUE * argv, VALUE klass);
|
|
|
|
extern VALUE qt_module;
|
|
|
|
extern VALUE qt_internal_module;
|
|
|
|
extern VALUE qt_base_class;
|
|
|
|
extern VALUE kde_module;
|
|
|
|
extern VALUE kio_module;
|
|
|
|
extern VALUE kparts_module;
|
|
|
|
extern VALUE khtml_module;
|
|
|
|
|
|
|
|
VALUE
|
|
|
|
getdcopinfo(VALUE self, TQString & signalname)
|
|
|
|
{
|
|
|
|
VALUE member = rb_funcall( kde_internal_module,
|
|
|
|
rb_intern("fullSignalName"),
|
|
|
|
2, self, rb_str_new2(signalname) );
|
|
|
|
signalname.setLatin1(StringValuePtr(member));
|
|
|
|
return rb_funcall( qt_internal_module,
|
|
|
|
rb_intern("getMocArguments"),
|
|
|
|
1, member );
|
|
|
|
}
|
|
|
|
|
|
|
|
VALUE
|
|
|
|
k_dcop_signal(int argc, VALUE * argv, VALUE self)
|
|
|
|
{
|
|
|
|
VALUE dcopObject = rb_funcall(kde_module, rb_intern("createDCOPObject"), 1, self);
|
|
|
|
|
|
|
|
TQString signalname(rb_id2name(rb_frame_last_func()));
|
|
|
|
VALUE args = getdcopinfo(self, signalname);
|
|
|
|
|
|
|
|
if(args == Qnil) return Qfalse;
|
|
|
|
|
|
|
|
EmitDCOPSignal signal(dcopObject, signalname.latin1(), argc, argv, args);
|
|
|
|
signal.next();
|
|
|
|
|
|
|
|
return Qtrue;
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
dcop_functions(VALUE self)
|
|
|
|
{
|
|
|
|
VALUE dcopObject = rb_funcall(kde_module, rb_intern("createDCOPObject"), 1, self);
|
|
|
|
return rb_funcall(dcopObject, rb_intern("functions"), 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
dcop_interfaces(VALUE self)
|
|
|
|
{
|
|
|
|
VALUE dcopObject = rb_funcall(kde_module, rb_intern("createDCOPObject"), 1, self);
|
|
|
|
return rb_funcall(dcopObject, rb_intern("interfaces"), 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
dcop_connect_signal(VALUE self, VALUE sender, VALUE senderObj, VALUE signal, VALUE slot, VALUE volatile_connect)
|
|
|
|
{
|
|
|
|
VALUE dcopObject = rb_funcall(kde_module, rb_intern("createDCOPObject"), 1, self);
|
|
|
|
return rb_funcall(dcopObject, rb_intern("connectDCOPSignal"), 5, sender, senderObj, signal, slot, volatile_connect);
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
dcop_disconnect_signal(VALUE self, VALUE sender, VALUE senderObj, VALUE signal, VALUE slot)
|
|
|
|
{
|
|
|
|
VALUE dcopObject = rb_funcall(kde_module, rb_intern("createDCOPObject"), 1, self);
|
|
|
|
return rb_funcall(dcopObject, rb_intern("disconnectDCOPSignal"), 4, sender, senderObj, signal, slot);
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
dcop_process(VALUE /*self*/, VALUE target, VALUE slotname, VALUE args, VALUE data, VALUE replyTypeName, VALUE replyType, VALUE replyData)
|
|
|
|
{
|
|
|
|
smokeruby_object *o = value_obj_info(data);
|
|
|
|
if (o == 0 || o->ptr == 0) {
|
|
|
|
return Qfalse;
|
|
|
|
}
|
|
|
|
TQByteArray * dataArray = (TQByteArray*) o->ptr;
|
|
|
|
|
|
|
|
o = value_obj_info(replyData);
|
|
|
|
if (o == 0 || o->ptr == 0) {
|
|
|
|
return Qfalse;
|
|
|
|
}
|
|
|
|
TQByteArray * replyArray = (TQByteArray*) o->ptr;
|
|
|
|
|
|
|
|
InvokeDCOPSlot dcopSlot(target, rb_intern(StringValuePtr(slotname)), args, *dataArray, replyTypeName, replyType, *replyArray);
|
|
|
|
dcopSlot.next();
|
|
|
|
|
|
|
|
return Qtrue;
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
dcop_call(int argc, VALUE * argv, VALUE /*self*/)
|
|
|
|
{
|
|
|
|
TQCString fun(StringValuePtr(argv[1]));
|
|
|
|
VALUE args = argv[2];
|
|
|
|
bool useEventLoop = (argv[argc-2] == Qtrue ? true : false);
|
|
|
|
int timeout = NUM2INT(argv[argc-1]);
|
|
|
|
|
|
|
|
DCOPCall dcopCall(argv[0], fun, argc-5, argv+3, args, useEventLoop, timeout);
|
|
|
|
dcopCall.next();
|
|
|
|
|
|
|
|
return *(dcopCall.var());
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
dcop_send(int argc, VALUE * argv, VALUE /*self*/)
|
|
|
|
{
|
|
|
|
TQCString fun(StringValuePtr(argv[1]));
|
|
|
|
VALUE args = argv[2];
|
|
|
|
VALUE result = Qnil;
|
|
|
|
|
|
|
|
DCOPSend dcopSend(argv[0], fun, argc-3, argv+3, args, &result);
|
|
|
|
dcopSend.next();
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
new_kde(int argc, VALUE * argv, VALUE klass)
|
|
|
|
{
|
|
|
|
VALUE instance = new_qt(argc, argv, klass);
|
|
|
|
|
|
|
|
if (rb_funcall(kde_module, rb_intern("hasDCOPSignals"), 1, klass) == Qtrue) {
|
|
|
|
VALUE signalNames = rb_funcall(kde_module, rb_intern("getDCOPSignalNames"), 1, klass);
|
|
|
|
for (long index = 0; index < RARRAY(signalNames)->len; index++) {
|
|
|
|
VALUE signal = rb_ary_entry(signalNames, index);
|
|
|
|
rb_define_method(klass, StringValuePtr(signal), (VALUE (*) (...)) k_dcop_signal, -1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( rb_funcall(kde_module, rb_intern("hasDCOPSlots"), 1, klass) == Qtrue
|
|
|
|
|| rb_funcall(kde_module, rb_intern("hasDCOPSignals"), 1, klass) == Qtrue )
|
|
|
|
{
|
|
|
|
VALUE dcop_object = rb_funcall(kde_module, rb_intern("createDCOPObject"), 1, instance);
|
|
|
|
if (dcop_object != Qnil) {
|
|
|
|
rb_define_method(klass, "interfaces", (VALUE (*) (...)) dcop_interfaces, 0);
|
|
|
|
rb_define_method(klass, "functions", (VALUE (*) (...)) dcop_functions, 0);
|
|
|
|
rb_define_method(klass, "connectDCOPSignal", (VALUE (*) (...)) dcop_connect_signal, 5);
|
|
|
|
rb_define_method(klass, "disconnectDCOPSignal", (VALUE (*) (...)) dcop_disconnect_signal, 4);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return instance;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if TDE_VERSION >= 0x030200
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
kconfigskeletonitem_immutable(VALUE self)
|
|
|
|
{
|
|
|
|
smokeruby_object *o = value_obj_info(self);
|
|
|
|
KConfigSkeletonItem * item = (KConfigSkeletonItem *) o->ptr;
|
|
|
|
return item->isImmutable() ? Qtrue : Qfalse;
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
config_additem(int argc, VALUE * argv, VALUE self)
|
|
|
|
{
|
|
|
|
smokeruby_object *o = value_obj_info(self);
|
|
|
|
KConfigSkeleton * config = (KConfigSkeleton *) o->ptr;
|
|
|
|
|
|
|
|
if (argc < 1 || argc > 2) {
|
|
|
|
rb_raise(rb_eArgError, "wrong number of arguments(%d for 2)\n", argc);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (TYPE(argv[0]) != T_DATA) {
|
|
|
|
rb_raise(rb_eArgError, "wrong argument type, expected KDE::ConfigSkeletonItem\n", argc);
|
|
|
|
}
|
|
|
|
|
|
|
|
smokeruby_object *c = value_obj_info(argv[0]);
|
|
|
|
KConfigSkeletonItem * item = (KConfigSkeletonItem *) c->ptr;
|
|
|
|
|
|
|
|
if (argc == 1) {
|
|
|
|
config->addItem(item);
|
|
|
|
} else {
|
|
|
|
config->addItem(item, TQString(StringValuePtr(argv[1])));
|
|
|
|
}
|
|
|
|
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
konsole_part_startprogram(VALUE self, VALUE value_program, VALUE value_args)
|
|
|
|
{
|
|
|
|
smokeruby_object * o = value_obj_info(self);
|
|
|
|
TerminalInterface * t = static_cast<TerminalInterface*>(((KParts::ReadOnlyPart*) o->ptr)->qt_cast("TerminalInterface"));
|
|
|
|
|
|
|
|
TQStrList *args = new TQStrList;
|
|
|
|
|
|
|
|
if (value_args != Qnil) {
|
|
|
|
for (long i = 0; i < RARRAY(value_args)->len; i++) {
|
|
|
|
VALUE item = rb_ary_entry(value_args, i);
|
|
|
|
args->append(TQString::fromLatin1(StringValuePtr(item), RSTRING(item)->len));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
t->startProgram(TQString::fromLatin1(StringValuePtr(value_program)), args);
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
konsole_part_showshellindir(VALUE self, VALUE value_dir)
|
|
|
|
{
|
|
|
|
smokeruby_object * o = value_obj_info(self);
|
|
|
|
TerminalInterface * t = static_cast<TerminalInterface*>(((KParts::ReadOnlyPart*) o->ptr)->qt_cast("TerminalInterface"));
|
|
|
|
t->showShellInDir(StringValuePtr(value_dir));
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
konsole_part_sendinput(VALUE self, VALUE value_text)
|
|
|
|
{
|
|
|
|
smokeruby_object * o = value_obj_info(self);
|
|
|
|
TerminalInterface * t = static_cast<TerminalInterface*>(((KParts::ReadOnlyPart*) o->ptr)->qt_cast("TerminalInterface"));
|
|
|
|
t->sendInput(StringValuePtr(value_text));
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if TDE_VERSION >= 0x030500
|
|
|
|
static VALUE
|
|
|
|
konsole_part_setautostartshell(VALUE self, VALUE enabled)
|
|
|
|
{
|
|
|
|
smokeruby_object * o = value_obj_info(self);
|
|
|
|
ExtTerminalInterface * t = static_cast<ExtTerminalInterface*>(((KParts::ReadOnlyPart*) o->ptr)->qt_cast("ExtTerminalInterface"));
|
|
|
|
t->setAutoStartShell(enabled == Qtrue);
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
konsole_part_setautodestroy(VALUE self, VALUE enabled)
|
|
|
|
{
|
|
|
|
smokeruby_object * o = value_obj_info(self);
|
|
|
|
ExtTerminalInterface * t = static_cast<ExtTerminalInterface*>(((KParts::ReadOnlyPart*) o->ptr)->qt_cast("ExtTerminalInterface"));
|
|
|
|
t->setAutoDestroy(enabled == Qtrue);
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
void
|
|
|
|
Init_korundum()
|
|
|
|
{
|
|
|
|
if (qt_internal_module != Qnil) {
|
|
|
|
rb_fatal("require 'Korundum' must not follow require 'Qt'\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
set_new_kde(new_kde);
|
|
|
|
#if TDE_VERSION >= 0x030200
|
|
|
|
set_kconfigskeletonitem_immutable(kconfigskeletonitem_immutable);
|
|
|
|
#endif
|
|
|
|
set_kde_resolve_classname(kde_resolve_classname);
|
|
|
|
|
|
|
|
// The Qt extension is linked against libsmokeqt.so, but Korundum links against
|
|
|
|
// libsmokekde.so only. Specifying both a 'require Qt' and a 'require Korundum',
|
|
|
|
// would give a link error (see the rb_fatal() error above).
|
|
|
|
// So call the Init_qtruby() initialization function explicitely, not via 'require Qt'
|
|
|
|
// (Qt.o is linked into libqtruby.so, as well as the Qt.so extension).
|
|
|
|
Init_qtruby();
|
|
|
|
install_handlers(KDE_handlers);
|
|
|
|
|
|
|
|
kde_internal_module = rb_define_module_under(kde_module, "Internal");
|
|
|
|
rb_define_singleton_method(kde_module, "dcop_process", (VALUE (*) (...)) dcop_process, 7);
|
|
|
|
rb_define_singleton_method(kde_module, "dcop_call", (VALUE (*) (...)) dcop_call, -1);
|
|
|
|
rb_define_singleton_method(kde_module, "dcop_send", (VALUE (*) (...)) dcop_send, -1);
|
|
|
|
|
|
|
|
#if TDE_VERSION >= 0x030200
|
|
|
|
rb_define_method(kconfigskeleton_class, "addItem", (VALUE (*) (...)) config_additem, -1);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
rb_define_method(konsole_part_class, "startProgram", (VALUE (*) (...)) konsole_part_startprogram, 2);
|
|
|
|
rb_define_method(konsole_part_class, "showShellInDir", (VALUE (*) (...)) konsole_part_showshellindir, 1);
|
|
|
|
rb_define_method(konsole_part_class, "sendInput", (VALUE (*) (...)) konsole_part_sendinput, 1);
|
|
|
|
#if TDE_VERSION >= 0x030500
|
|
|
|
rb_define_method(konsole_part_class, "setAutoStartShell", (VALUE (*) (...)) konsole_part_setautostartshell, 1);
|
|
|
|
rb_define_method(konsole_part_class, "autoStartShell=", (VALUE (*) (...)) konsole_part_setautostartshell, 1);
|
|
|
|
rb_define_method(konsole_part_class, "setAutoDestroy", (VALUE (*) (...)) konsole_part_setautodestroy, 1);
|
|
|
|
rb_define_method(konsole_part_class, "autoDestroy=", (VALUE (*) (...)) konsole_part_setautodestroy, 1);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
rb_require("KDE/korundum.rb");
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|