[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