[Kde-bindings] KDE/kdebindings/ruby/qtruby
Richard Dale
Richard_Dale at tipitina.demon.co.uk
Mon Jun 18 09:51:07 UTC 2007
SVN commit 677023 by rdale:
* When a Qt::Object is subclassed more than once, a Qt::MetaObject is
now correctly constructed for each subclass. Before a half-working
hack was used where a Qt::MetaObject containing all the slots and
signal of its superclass too, was constructed for the twice sub-classed
class. Fixes problems reported by Caleb Tennis amoungst several others.
CCMAIL: kde-bindings at kde.org
M +8 -0 ChangeLog
M +73 -52 src/Qt.cpp
M +19 -38 src/lib/Qt/qtruby4.rb
--- trunk/KDE/kdebindings/ruby/qtruby/ChangeLog #677022:677023
@@ -1,3 +1,11 @@
+2007-06-18 Richard Dale <rdale at foton.es>
+
+ * When a Qt::Object is subclassed more than once, a Qt::MetaObject is
+ now correctly constructed for each subclass. Before a half-working
+ hack was used where a Qt::MetaObject containing all the slots and
+ signal of its superclass too, was constructed for the twice sub-classed
+ class. Fixes problems reported by Caleb Tennis amoungst several others.
+
2007-06-12 Richard Dale <rdale at foton.es>
* Added some missing list marshallers
--- trunk/KDE/kdebindings/ruby/qtruby/src/Qt.cpp #677022:677023
@@ -1582,7 +1582,7 @@
static VALUE
metaObject(VALUE self)
{
- VALUE metaObject = rb_funcall(qt_internal_module, rb_intern("getMetaObject"), 1, self);
+ VALUE metaObject = rb_funcall(qt_internal_module, rb_intern("getMetaObject"), 2, Qnil, self);
return metaObject;
}
@@ -2072,7 +2072,7 @@
getmetainfo(VALUE self, int &offset, int &index)
{
char * signalname = rb_id2name(rb_frame_last_func());
- VALUE metaObject_value = rb_funcall(qt_internal_module, rb_intern("getMetaObject"), 1, self);
+ VALUE metaObject_value = rb_funcall(qt_internal_module, rb_intern("getMetaObject"), 2, Qnil, self);
smokeruby_object *ometa = value_obj_info(metaObject_value);
if(!ometa) return 0;
@@ -2128,31 +2128,23 @@
// it isn't an error to get a NULL value of _o here.
Data_Get_Struct(argv[2], void*, _o);
- VALUE metaObject_value = rb_funcall(qt_internal_module, rb_intern("getMetaObject"), 1, self);
- smokeruby_object *ometa = value_obj_info(metaObject_value);
- if (!ometa) return argv[1];
-
- QMetaObject *metaobject = (QMetaObject*)ometa->ptr;
-
- int count = metaobject->methodCount();
- int offset = metaobject->methodOffset();
-
- if (id < offset) {
- // Assume the target slot is a C++ one
- smokeruby_object *o = value_obj_info(self);
- Smoke::Index nameId = o->smoke->idMethodName("qt_metacall$$?");
- Smoke::Index meth = o->smoke->findMethod(o->classId, nameId);
- if(meth > 0) {
- Smoke::Method &m = o->smoke->methods[o->smoke->methodMaps[meth].method];
- Smoke::ClassFn fn = o->smoke->classes[m.classId].classFn;
- Smoke::StackItem i[4];
- i[1].s_enum = _c;
- i[2].s_int = id;
- i[3].s_voidp = _o;
- (*fn)(m.method, o->ptr, i);
- return INT2NUM(i[0].s_int);
+ // Assume the target slot is a C++ one
+ smokeruby_object *o = value_obj_info(self);
+ Smoke::Index nameId = o->smoke->idMethodName("qt_metacall$$?");
+ Smoke::Index meth = o->smoke->findMethod(o->classId, nameId);
+ if (meth > 0) {
+ Smoke::Method &m = o->smoke->methods[o->smoke->methodMaps[meth].method];
+ Smoke::ClassFn fn = o->smoke->classes[m.classId].classFn;
+ Smoke::StackItem i[4];
+ i[1].s_enum = _c;
+ i[2].s_int = id;
+ i[3].s_voidp = _o;
+ (*fn)(m.method, o->ptr, i);
+ int ret = i[0].s_int;
+ if (ret < 0) {
+ return INT2NUM(ret);
}
-
+ } else {
// Should never happen..
rb_raise(rb_eRuntimeError, "Cannot find %s::qt_metacall() method\n",
o->smoke->classes[o->classId].className );
@@ -2162,24 +2154,43 @@
return argv[1];
}
- QMetaMethod method = metaobject->method(id);
+ QObject *qobj = (QObject*) o->ptr;
+ // get obj metaobject with a virtual call
+ const QMetaObject *metaobject = qobj->metaObject();
- VALUE mocArgs = rb_funcall( qt_internal_module,
- rb_intern("getMocArguments"),
- 2,
- rb_str_new2(method.typeName()),
- rb_str_new2(method.signature()) );
+ // get method/property count
+ int count = 0;
+ if (_c == QMetaObject::InvokeMetaMethod) {
+ count = metaobject->methodCount();
+ } else {
+ count = metaobject->propertyCount();
+ }
- QString name(method.signature());
+ if (_c == QMetaObject::InvokeMetaMethod) {
+ QMetaMethod method = metaobject->method(id);
+
+ if (method.methodType() == QMetaMethod::Signal) {
+ metaobject->activate(qobj, _id, (void**) _o);
+ return INT2NUM(id - count);
+ }
+
+ VALUE mocArgs = rb_funcall( qt_internal_module,
+ rb_intern("getMocArguments"),
+ 2,
+ rb_str_new2(method.typeName()),
+ rb_str_new2(method.signature()) );
+
+ QString name(method.signature());
static QRegExp * rx = 0;
- if (rx == 0) {
- rx = new QRegExp("\\(.*");
+ if (rx == 0) {
+ rx = new QRegExp("\\(.*");
+ }
+ name.replace(*rx, "");
+
+ InvokeSlot slot(self, rb_intern(name.toLatin1()), mocArgs, _o);
+ slot.next();
}
- name.replace(*rx, "");
- InvokeSlot slot(self, rb_intern(name.toLatin1()), mocArgs, _o);
- slot.next();
-
return INT2NUM(id - count);
}
@@ -2504,29 +2515,39 @@
return rb_str_new2(get_VALUEtype(ruby_value));
}
-static VALUE
-make_metaObject(VALUE /*self*/, VALUE obj, VALUE stringdata_value, VALUE data_value)
+static QMetaObject*
+parent_meta_object(VALUE obj)
{
- smokeruby_object *o = value_obj_info(obj);
- if (!o || !o->ptr) {
- rb_raise(rb_eRuntimeError, "Cannot create metaObject\n");
- }
-
+ smokeruby_object* o = value_obj_info(obj);
Smoke::Index nameId = o->smoke->idMethodName("metaObject");
Smoke::Index meth = o->smoke->findMethod(o->classId, nameId);
if (meth <= 0) {
// Should never happen..
- rb_raise( rb_eRuntimeError,
- "Cannot find %s::metaObject() method\n",
- o->smoke->classes[o->classId].className );
}
Smoke::Method &methodId = o->smoke->methods[o->smoke->methodMaps[meth].method];
Smoke::ClassFn fn = o->smoke->classes[methodId.classId].classFn;
Smoke::StackItem i[1];
(*fn)(methodId.method, o->ptr, i);
+ return (QMetaObject*) i[0].s_voidp;
+}
- QMetaObject *superdata = (QMetaObject *) i[0].s_voidp;
+static VALUE
+make_metaObject(VALUE /*self*/, VALUE obj, VALUE parentMeta, VALUE stringdata_value, VALUE data_value)
+{
+ QMetaObject* superdata = 0;
+
+ if (parentMeta == Qnil) {
+ // The parent class is a Smoke class, so call metaObject() on the
+ // instance to get it via a smoke library call
+ superdata = parent_meta_object(obj);
+ } else {
+ // The parent class is a custom Ruby class whose metaObject
+ // was constructed at runtime
+ smokeruby_object* p = value_obj_info(parentMeta);
+ superdata = (QMetaObject *) p->ptr;
+ }
+
char *stringdata = new char[RSTRING(stringdata_value)->len];
int count = RARRAY(data_value)->len;
@@ -2616,7 +2637,7 @@
printf("%c", meta->d.stringdata[j]);
}
}
- printf("\"\n");
+ printf("\"\n\n");
#endif
smokeruby_object * m = alloc_smokeruby_object( true,
@@ -3361,7 +3382,7 @@
rb_define_module_function(qt_internal_module, "find_pclassid", (VALUE (*) (...)) find_pclassid, 1);
rb_define_module_function(qt_internal_module, "getVALUEtype", (VALUE (*) (...)) getVALUEtype, 1);
- rb_define_module_function(qt_internal_module, "make_metaObject", (VALUE (*) (...)) make_metaObject, 3);
+ rb_define_module_function(qt_internal_module, "make_metaObject", (VALUE (*) (...)) make_metaObject, 4);
rb_define_module_function(qt_internal_module, "addMetaObjectMethods", (VALUE (*) (...)) add_metaobject_methods, 1);
rb_define_module_function(qt_internal_module, "addSignalMethods", (VALUE (*) (...)) add_signal_methods, 2);
rb_define_module_function(qt_internal_module, "mapObject", (VALUE (*) (...)) mapObject, 1);
--- trunk/KDE/kdebindings/ruby/qtruby/src/lib/Qt/qtruby4.rb #677022:677023
@@ -2393,16 +2393,6 @@
end
end
- def Internal.signalAt(qobject, index)
- classname = qobject.class.name
- Meta[classname].get_signals[index].full_name
- end
-
- def Internal.slotAt(qobject, index)
- classname = qobject.class.name
- Meta[classname].get_slots[index].full_name
- end
-
def Internal.getMocArguments(reply_type, member)
argStr = member.sub(/.*\(/, '').sub(/\)$/, '')
args = argStr.scan(/([^,]*<[^>]+>)|([^,]+)/)
@@ -2505,24 +2495,28 @@
return [stringdata.pack(pack_string), data]
end
- def Internal.getMetaObject(qobject)
- klass = qobject.class
- begin
- meta = Meta[klass.name]
- klass = klass.superclass
- end while meta.nil? and klass != Object
+ def Internal.getMetaObject(klass, qobject)
+ if klass.nil?
+ klass = qobject.class
+ end
- return nil if meta.nil?
-
+ parentMeta = nil
+ if @@cpp_names[klass.superclass.name].nil?
+ parentMeta = getMetaObject(klass.superclass, qobject)
+ end
+
+ meta = Meta[klass.name]
+ if meta.nil?
+ meta = Qt::MetaInfo.new(klass)
+ end
+
if meta.metaobject.nil? or meta.changed
- signals = meta.get_signals
- slots = meta.get_slots
- stringdata, data = makeMetaData( qobject.class.name,
+ stringdata, data = makeMetaData( qobject.class.name,
meta.classinfos,
meta.dbus,
- signals,
- slots)
- meta.metaobject = make_metaObject(qobject, stringdata, data)
+ meta.signals,
+ meta.slots )
+ meta.metaobject = make_metaObject(qobject, parentMeta, stringdata, data)
meta.changed = false
addSignalMethods(qobject.class, getSignalNames(qobject.class))
end
@@ -2562,6 +2556,7 @@
class MetaInfo
attr_accessor :classinfos, :dbus, :signals, :slots, :metaobject, :mocargs, :changed
+
def initialize(klass)
Meta[klass.name] = self
@klass = klass
@@ -2615,20 +2610,6 @@
end
end
end
-
- # Return a list of slots, including inherited ones
- def get_slots
- all_slots = []
- current = @klass
- while current != Qt::Base
- meta = Meta[current.name]
- if !meta.nil?
- all_slots.concat meta.slots
- end
- current = current.superclass
- end
- return all_slots
- end
def add_classinfo(key, value)
@classinfos.push [key, value]
More information about the Kde-bindings
mailing list