[Kde-bindings] Qt::Object.connect for ruby-blocks

Richard Dale rdale at foton.es
Mon Sep 4 10:03:37 UTC 2006


On Saturday 02 September 2006 17:05, kelko wrote:
> Hi,
> In #kde-ruby there started a discussion of being able to pass a block
> directly to Qt::Object.connect so it is called everytime a signal is
> emitted. working on it and talking about it witch Richard i wrote code
> to add support for such calls to qtruby.
> Actually it has to be called another method to support block yet, but
> we want to get it working directly in the same method.
>
> When the file appended is required in a ruby-app you can do things like:
> Qt::Object.connect2Block(Qt::PushButton.new(), SIGNAL("clicked()")) do
> 	puts "Hello World"
> end
>
> In the block you can access other objects available in the context
> where the block was created.
>
> You can even work with signals having arguments:
>
> Qt::Object.connect2Block(KDE::HTMLPart.new().browserExtension,
> SIGNAL("openURLRequestedDelayed(const KURL&, const KParts::URLArgs&)")
> do | kurl, args|
> 		puts kurl.url
> end
>
> Both of the calls I checked and they are working.
>
> The way this new methods work is quite simple:
> it take the block passed and passes it to a new created "proxy" (an
> instance of Qt::BlockInvocator) altogether with the arguments of the
> signal. the BlockInvotator creates the slots "process" with the very
> arguments of the signal so it fits perfectly. Then the signal will be
> connect using the normal Qt::Object.connect to the slots "process" of
> the instance of BlockInvocator.
Yes, I like this idea and it will be very useful for QtRuby programming. I had 
been thinking of adding a new slot with the name based on the address of the 
block or something. But using a 'proxy' object to handle the block invocation 
is better and simpler.

I'd like to change the other forms of connect() too so they can take blocks 
too. Eg:

connect(a, SIGNAL(:siga), b, SLOT(:slotb)) could have one less argument and 
take a block instead:

connect(a, SIGNAL(:siga), b) { ... }

I thought about how the BlockInvocator would work with garbage collection, and 
I think we need to give it the target QObject in its constructor and that 
would become the parent QObject. Otherwise there would be no references to 
the BlockInvocator in Ruby and it could get gc'd. I think I prefer the 
name 'Qt::Proc', but the user would never use it directly so it doesn't 
matter too much.

Another issue is how to invoke the block - in you code you have:

@toCall.call(*vars)

So is that evaluated in the context you originally passed the block, and not 
the context that the target of the slot now has? I'm not sure and would have 
to experiment.

I wonder if it should be like this instead, especially for the example 
connect() I give above:

parent.instance_eval(@toCall)

But then I don't see how you pass arguments to the block in that form.

-- Richard



More information about the Kde-bindings mailing list