[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