[Kde-bindings] KDE/kdebindings/qtruby
Richard Dale
Richard_Dale at tipitina.demon.co.uk
Fri Feb 16 10:59:30 UTC 2007
SVN commit 634098 by rdale:
* Thomas Moenicke fixed the qtruby cmake build so it works on
all machines by adding a KDE_EXPORT macro to Init_qtruby4().
Big thanks to Thomas and Guillaume Laurent for getting it all working.
* Added calling slots directly in custom C++ QObject classes.
If a method isn't found in the Smoke library, and the instance is
a kind of QObject with a class not in the Smoke library, then look
for a slot matching the method name and invoke it. Thanks to Eric Landuy
for the idea and discussion leading to implementing it.
* Added a check for QtDBus in the qtruby cmake file and set a define
of -DQT_QTDBUS if the library was found
* Changed the ADD_LIBRARY line in the qtruby cmake file to use MODULE
so that a bundle should be built on Mac OS X.
CCMAIL: kde-bindings at kde.org
CCMAIL: eric at datarescue.com
M +15 -0 ChangeLog
M +11 -3 rubylib/qtruby/CMakeLists.txt
M +151 -18 rubylib/qtruby/Qt.cpp
M +13 -0 rubylib/qtruby/marshall_types.h
--- trunk/KDE/kdebindings/qtruby/ChangeLog #634097:634098
@@ -1,3 +1,18 @@
+2007-02-16 Richard Dale <rdale at foton.es>
+
+ * Thomas Moenicke fixed the qtruby cmake build so it works on
+ all machines by adding a KDE_EXPORT macro to Init_qtruby4()
+ Big thanks to Thomas and Guillaume Laurent for getting it all working.
+ * Added calling slots directly in custom C++ QObject classes.
+ If a method isn't found in the Smoke library, and the instance is
+ a kind of QObject with a class not in the Smoke library, then look
+ for a slot matching the method name and invoke it. Thanks to Eric Landuy
+ for the idea and discussion leading to implementing it.
+ * Added a check for QtDBus in the qtruby cmake file and set a define
+ of -DQT_QTDBUS if the library was found
+ * Changed the ADD_LIBRARY line in the qtruby cmake file to use MODULE
+ so that a bundle should be built on Mac OS X.
+
2007-02-08 Richard Dale <rdale at foton.es>
* Fixed bugs in the debug dump of QMetaObjects created at runtime
--- trunk/KDE/kdebindings/qtruby/rubylib/qtruby/CMakeLists.txt #634097:634098
@@ -1,7 +1,12 @@
add_subdirectory( lib )
+IF(QT_QTDBUS_FOUND)
+ ADD_DEFINITIONS (-DQT_QTDBUS)
+ENDIF(QT_QTDBUS_FOUND)
+
include_directories( ${CMAKE_SOURCE_DIR}/smoke ${RUBY_INCLUDE_PATH} )
+INCLUDE_DIRECTORIES (${QT_INCLUDES})
set(qtruby_LIB_SRCS
@@ -10,14 +15,17 @@
marshall_types.cpp
)
-kde4_add_library(qtruby4 SHARED ${qtruby_LIB_SRCS})
+# Use 'MODULE' instead of 'SHARED' so that qtruby will be built as a bundle on Mac OS X
+# instead of a dyld. But is this correct (rjd)? It needs testing.
+add_library(qtruby4 MODULE ${qtruby_LIB_SRCS})
+#add_library(qtruby4 SHARED ${qtruby_LIB_SRCS})
-target_link_libraries(qtruby4 ${KDE4_KDECORE_LIBS} ${RUBY_LIBRARY} ${QT_QTNETWORK_LIBRARY} smokeqt)
+target_link_libraries(qtruby4 ${QT_QTCORE_LIBRARY} ${RUBY_LIBRARY} ${QT_QTNETWORK_LIBRARY} smokeqt)
set_target_properties(qtruby4 PROPERTIES VERSION 0.0.0 SOVERSION 0 PREFIX "")
+
install(TARGETS qtruby4 DESTINATION ${RUBY_SITE_ARCH_DIR} )
-
########### next target ###############
--- trunk/KDE/kdebindings/qtruby/rubylib/qtruby/Qt.cpp #634097:634098
@@ -45,6 +45,10 @@
#include <QtCore/qabstractitemmodel.h>
#include <QtGui/qitemselectionmodel.h>
+#ifdef QT_QTDBUS
+#include <QtDBus/qdbusargument.h>
+#endif
+
extern bool qRegisterResourceData(int, const unsigned char *, const unsigned char *, const unsigned char *);
extern bool qUnregisterResourceData(int, const unsigned char *, const unsigned char *, const unsigned char *);
@@ -441,6 +445,60 @@
return true;
}
+InvokeNativeSlot::InvokeNativeSlot(QObject *obj, int id, int items, VALUE args, VALUE *sp, VALUE * result) : SigSlotBase(args),
+ _obj(obj), _id(id)
+{
+ _sp = sp;
+ _result = result;
+}
+
+Marshall::Action
+InvokeNativeSlot::action()
+{
+ return Marshall::FromVALUE;
+}
+
+Smoke::StackItem &
+InvokeNativeSlot::item()
+{
+ return _stack[_cur];
+}
+
+const char *
+InvokeNativeSlot::mytype()
+{
+ return "slot";
+}
+
+void
+InvokeNativeSlot::invokeSlot()
+{
+ if (_called) return;
+ _called = true;
+ void ** o = new void*[_items];
+ smokeStackToQtStack(_stack, o + 1, _items - 1, _args + 1);
+ void * ptr;
+ o[0] = &ptr;
+ _obj->qt_metacall(QMetaObject::InvokeMetaMethod, _id, o);
+
+ if (_args[0].argType != xmoc_void) {
+ SignalReturnValue r(o, _result, _args);
+ }
+ delete[] o;
+}
+
+void
+InvokeNativeSlot::mainfunction()
+{
+ invokeSlot();
+}
+
+bool
+InvokeNativeSlot::cleanup()
+{
+ return true;
+}
+
void rb_str_catf(VALUE self, const char *format, ...)
{
#define CAT_BUFFER_SIZE 2048
@@ -1303,6 +1361,44 @@
return self;
}
+#ifdef QT_QTDBUS
+static VALUE
+qdbusargument_endarraywrite(VALUE self)
+{
+ smokeruby_object *o = value_obj_info(self);
+ QDBusArgument * arg = (QDBusArgument *) o->ptr;
+ arg->endArray();
+ return self;
+}
+
+static VALUE
+qdbusargument_endmapwrite(VALUE self)
+{
+ smokeruby_object *o = value_obj_info(self);
+ QDBusArgument * arg = (QDBusArgument *) o->ptr;
+ arg->endMap();
+ return self;
+}
+
+static VALUE
+qdbusargument_endmapentrywrite(VALUE self)
+{
+ smokeruby_object *o = value_obj_info(self);
+ QDBusArgument * arg = (QDBusArgument *) o->ptr;
+ arg->endMapEntry();
+ return self;
+}
+
+static VALUE
+qdbusargument_endstructurewrite(VALUE self)
+{
+ smokeruby_object *o = value_obj_info(self);
+ QDBusArgument * arg = (QDBusArgument *) o->ptr;
+ arg->endStructure();
+ return self;
+}
+#endif
+
// The QtRuby runtime's overloaded method resolution mechanism can't currently
// distinguish between Ruby Arrays containing different sort of instances.
// Unfortunately Qt::Painter.drawLines() and Qt::Painter.drawRects() methods can
@@ -1665,40 +1761,70 @@
}
if (_current_method == -1) {
-
- // Check for property getter/setter calls
+ // Check for property getter/setter calls, and for slots in QObject classes
+ // not in the smoke library
smokeruby_object *o = value_obj_info(self);
if ( o != 0
&& o->ptr != 0
&& isDerivedFrom(o->smoke, o->classId, o->smoke->idClass("QObject")) )
{
QObject * qobject = (QObject *) o->smoke->cast(o->ptr, o->classId, o->smoke->idClass("QObject"));
-static QByteArray * prop = 0;
- if (prop == 0) {
- prop = new QByteArray();
+static QByteArray * name = 0;
+ if (name == 0) {
+ name = new QByteArray();
}
- *prop = rb_id2name(SYM2ID(argv[0]));
+ *name = rb_id2name(SYM2ID(argv[0]));
const QMetaObject * meta = qobject->metaObject();
if (argc == 1) {
- if (prop->endsWith("?")) {
- prop->replace(0, 1, pred->mid(0, 1).toUpper());
- prop->replace(0, 0, "is");
- if (meta->indexOfProperty(*prop) == -1) {
- prop->replace(0, 2, "has");
+ if (name->endsWith("?")) {
+ name->replace(0, 1, pred->mid(0, 1).toUpper());
+ name->replace(0, 0, "is");
+ if (meta->indexOfProperty(*name) == -1) {
+ name->replace(0, 2, "has");
}
}
- if (meta->indexOfProperty(*prop) != -1) {
- VALUE qvariant = rb_funcall(self, rb_intern("property"), 1, rb_str_new2(*prop));
- return rb_funcall(qvariant, rb_intern("to_ruby"), 0);
+ if (meta->indexOfProperty(*name) != -1) {
+ VALUE qvariant = rb_funcall(self, rb_intern("property"), 1, rb_str_new2(*name));
+ return rb_funcall(qvariant, rb_intern("value"), 0);
}
- } else if (argc == 2 && prop->endsWith("=")) {
- prop->replace("=", "");
- if (meta->indexOfProperty(*prop) != -1) {
+ } else if (argc == 2 && name->endsWith("=")) {
+ name->replace("=", "");
+ if (meta->indexOfProperty(*name) != -1) {
VALUE qvariant = rb_funcall(self, rb_intern("qVariantFromValue"), 1, argv[1]);
- return rb_funcall(self, rb_intern("setProperty"), 2, rb_str_new2(*prop), qvariant);
+ return rb_funcall(self, rb_intern("setProperty"), 2, rb_str_new2(*name), qvariant);
}
+ } else {
+ int classId = o->smoke->idClass(meta->className());
+ // The class isn't in the Smoke lib..
+ while (classId == 0) {
+ // Assume the QObject has slots which aren't in the Smoke library, so try
+ // and call the slot directly
+ for (int id = meta->methodOffset(); id < meta->methodCount(); id++) {
+ if (meta->method(id).methodType() == QMetaMethod::Slot) {
+ QByteArray signature(meta->method(id).signature());
+ QByteArray methodName = signature.mid(0, signature.indexOf('('));
+
+ // Don't check that the types of the ruby args match the c++ ones for now,
+ // only that the name and arg count is the same.
+ if (*name == methodName && signature.count(',') == (argc - 2)) {
+ VALUE args = rb_funcall( qt_internal_module,
+ rb_intern("getMocArguments"),
+ 2,
+ rb_str_new2(meta->method(id).typeName()),
+ rb_str_new2(meta->method(id).signature()) );
+
+ VALUE result = Qnil;
+ InvokeNativeSlot slot(qobject, id, argc - 1, args, argv + 1, &result);
+ slot.next();
+ return result;
+ }
+ }
+ }
+ meta = meta->superClass();
+ classId = o->smoke->idClass(meta->className());
+ }
}
}
@@ -3075,6 +3201,13 @@
rb_define_method(klass, "drawRects", (VALUE (*) (...)) qpainter_drawrects, -1);
} else if (packageName == "Qt::ModelIndex") {
rb_define_method(klass, "internalPointer", (VALUE (*) (...)) qmodelindex_internalpointer, 0);
+#ifdef QT_QTDBUS
+ } else if (packageName == "Qt::DBusArgument") {
+ rb_define_method(klass, "endArrayWrite", (VALUE (*) (...)) qdbusargument_endarraywrite, 0);
+ rb_define_method(klass, "endMapEntryWrite", (VALUE (*) (...)) qdbusargument_endmapentrywrite, 0);
+ rb_define_method(klass, "endMapWrite", (VALUE (*) (...)) qdbusargument_endmapwrite, 0);
+ rb_define_method(klass, "endStructureWrite", (VALUE (*) (...)) qdbusargument_endstructurewrite, 0);
+#endif
}
free((void *) package);
--- trunk/KDE/kdebindings/qtruby/rubylib/qtruby/marshall_types.h #634097:634098
@@ -199,6 +199,19 @@
bool cleanup();
};
+class InvokeNativeSlot : public SigSlotBase {
+ QObject *_obj;
+ int _id;
+ VALUE * _result;
+ public:
+ InvokeNativeSlot(QObject *obj, int id, int items, VALUE args, VALUE * sp, VALUE * result);
+ Marshall::Action action();
+ Smoke::StackItem &item();
+ const char *mytype();
+ void invokeSlot();
+ void mainfunction();
+ bool cleanup();
+};
class InvokeSlot : public SigSlotBase {
VALUE _obj;
More information about the Kde-bindings
mailing list