[Kde-bindings] branches/KDE/3.5/kdebindings/qtruby
Richard Dale
Richard_Dale at tipitina.demon.co.uk
Wed Sep 13 17:29:13 UTC 2006
SVN commit 583859 by rdale:
* Blocks can now be used as slots in Qt::Object.connect() calls. There are two
versions, a singleton method and an instance method.
* Here is an example of the class method connect() call with a block as a target:
app = Qt::Application.new(ARGV)
quit = Qt::PushButton.new('Quit')
Qt::Object.connect(quit, SIGNAL('clicked()'), app) { puts 'quit clicked' }
The block is executed in the context of the target instance, 'app' in this
case.
* And the instance method form:
class MyButton < Qt::Button
def initialize(text)
super(text)
connect(self, SIGNAL('clicked()')) { puts 'button clicked' }
end
...
The block is executed in the context of self - the instance making the
connect() call.
* The Rails version of the Ruby 1.9 method Object#instance_exec was used
to invoke the block. Thanks to kelko on the #kde-ruby channel for the
idea and the code, and #rickdangerous for further discussion.
CCMAIL: kde-bindings at kde.org
M +30 -0 ChangeLog
M +17 -0 rubylib/qtruby/Qt.cpp
M +43 -0 rubylib/qtruby/lib/Qt/qtruby.rb
--- branches/KDE/3.5/kdebindings/qtruby/ChangeLog #583858:583859
@@ -1,3 +1,33 @@
+2006-09-13 Richard Dale <rdale at foton.es>
+
+ * Blocks can now be used as slots in Qt::Object.connect() calls. There are two
+ versions, a singleton method and an instance method.
+
+ * Here is an example of the class method connect() call with a block as a target:
+
+ app = Qt::Application.new(ARGV)
+ quit = Qt::PushButton.new('Quit')
+ Qt::Object.connect(quit, SIGNAL('clicked()'), app) { puts 'quit clicked' }
+
+ The block is executed in the context of the target instance, 'app' in this
+ case.
+
+ * And the instance method form:
+
+ class MyButton < Qt::Button
+ def initialize(text)
+ super(text)
+ connect(self, SIGNAL('clicked()')) { puts 'button clicked' }
+ end
+ ...
+
+ The block is executed in the context of self - the instance making the
+ connect() call.
+
+ * The Rails version of the Ruby 1.9 method Object#instance_exec was used
+ to invoke the block. Thanks to kelko on the #kde-ruby channel for the
+ idea and the code, and #rickdangerous for further discussion.
+
2006-08-29 Richard Dale <rdale at foton.es>
* Backported some memory leak fixes from Qt4 QtRuby
--- branches/KDE/3.5/kdebindings/qtruby/rubylib/qtruby/Qt.cpp #583858:583859
@@ -1853,6 +1853,21 @@
return Qtrue;
}
+static VALUE
+qobject_connect(int argc, VALUE * argv, VALUE self)
+{
+ if (rb_block_given_p()) {
+ if (argc == 2) {
+ return rb_funcall(qt_internal_module, rb_intern("connect"), 4, argv[0], argv[1], self, rb_block_proc());
+ } else if (argc == 3) {
+ return rb_funcall(qt_internal_module, rb_intern("connect"), 4, argv[0], argv[1], argv[2], rb_block_proc());
+ } else {
+ rb_raise(rb_eArgError, "Invalid argument list");
+ }
+ } else {
+ return rb_call_super(argc, argv);
+ }
+}
// --------------- Ruby C functions for Qt::_internal.* helpers ----------------
@@ -2695,6 +2710,8 @@
rb_define_method(klass, "receivers", (VALUE (*) (...)) receivers_qobject, 0);
rb_define_method(klass, "className", (VALUE (*) (...)) class_name, 0);
rb_define_method(klass, "inherits", (VALUE (*) (...)) inherits_qobject, -1);
+ rb_define_method(klass, "connect", (VALUE (*) (...)) qobject_connect, -1);
+ rb_define_singleton_method(klass, "connect", (VALUE (*) (...)) qobject_connect, -1);
return klass;
}
--- branches/KDE/3.5/kdebindings/qtruby/rubylib/qtruby/lib/Qt/qtruby.rb #583858:583859
@@ -1204,6 +1204,19 @@
return !@value
end
end
+
+ class BlockInvocation < Qt::Object
+ def initialize(target, block, args)
+ super(target)
+ self.class.slots "invoke(#{args})"
+ @target = target
+ @block = block
+ end
+
+ def invoke(*args)
+ @target.instance_exec(*args, &@block)
+ end
+ end
module Internal
@@classes = {}
@@ -1601,6 +1614,14 @@
meta.metaobject
end
+
+ def Internal.connect(src, signal, target, block)
+ signature = (signal =~ /\((.*)\)/) ? $1 : ""
+ return Qt::Object.connect( src,
+ signal,
+ Qt::BlockInvocation.new(target, block, signature),
+ SLOT("invoke(#{signature})") )
+ end
end # Qt::Internal
Meta = {}
@@ -1730,8 +1751,30 @@
def emit(signal)
return signal
end
+
+ # See the discussion here: http://eigenclass.org/hiki.rb?instance_exec
+ # about implementations of the ruby 1.9 method instance_exec(). This
+ # version is the one from Rails. It isn't thread safe, but that doesn't
+ # matter for the intended use in invoking blocks as Qt slots.
+ def instance_exec(*arguments, &block)
+ block.bind(self)[*arguments]
+ end
end
+class Proc
+ # Part of the Rails Object#instance_exec implementation
+ def bind(object)
+ block, time = self, Time.now
+ (class << object; self end).class_eval do
+ method_name = "__bind_#{time.to_i}_#{time.usec}"
+ define_method(method_name, &block)
+ method = instance_method(method_name)
+ remove_method(method_name)
+ method
+ end.bind(object)
+ end
+end
+
class Module
alias_method :_constants, :constants
alias_method :_instance_methods, :instance_methods
More information about the Kde-bindings
mailing list