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

kelko kelko at anakrino.de
Mon Sep 4 11:05:28 UTC 2006


Richard Dale wrote:
> 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) { ... }

Why would you want to bind a block to a target? (the third argument)
For if the block executes in the context of where it was created then I
for myself don't see a need for such a thing.

> 
> 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.

Good point about the garbage collector.
What about registering the BlockInvocator as child of the source of
the signal?
Then there would be no need for a third argument for a connect-call.
An other way would be to create a @@procs = [] containing all ever
created BlockInvocators. But that ain't pretty.


> I think I prefer the name 'Qt::Proc', but the user would never use
> it directly so it doesn't matter too much.

Yeah, that's why I haven't called it Qt::Proc for the proxy doesn't
seem to fit the name "Proc" for it can't be used by developers inside
the apps as Qt-Version of ruby-procs.


> 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 tried at home such a call and it worked, but will try more today
when i am back home:
@button = KDE::PushButton.new(self)
Qt::Object.connect2Block(@button, SIGNAL('clicked()')) {
    @button.text = "Hi"
}

When i pressed the button the text of it changed.



More information about the Kde-bindings mailing list