[Kde-bindings] questions about signals and slots in qruby4

Richard Dale rdale at foton.es
Tue Aug 5 09:07:56 UTC 2008


On Tuesday 05 August 2008 08:03:54 Stefano Crocco wrote:
> On Monday 04 August 2008, Richard Dale wrote:
> > On Sunday 03 August 2008 14:23:10 Stefano Crocco wrote:
> > > I have a few questions about signals, slots and connections in qtruby4:
> > >
> > > * 'connect' if called with an explicit receiver wants a block and
> > > raises an error if called in the non-block form. For example, the
> > > following code works:
> > >
> > > require 'Qt4'
> > >
> > > app =  Qt::Application.new []
> > > btn = Qt::PushButton.new "Sender"
> > > label = Qt::Label.new "Receiver"
> > > btn.connect(SIGNAL('clicked()')){label.clear}
> > > btn.show
> > > label.show
> > > app.exec
> > >
> > > but if I replace the connect line with:
> > >
> > > btn.connect(SIGNAL('clicked()'), label, SLOT('clear()'))
> > >
> > > I get the following error:
> > >
> > > ./prova.rb:9:in `method_missing': super: no superclass method `connect'
> > > (NoMethodError)
> > >         from ./prova.rb:9:in `connect'
> > >         from ./prova.rb:9
> > >
> > > (At first, I thought the error might have had been caused by calling
> > > connect from the top-level object, given that it spoke about a missing
> > > superclass method, but trying it inside an instance method of a
> > > Qt::Widget-derived class gave the same result). Is this wanted, or is
> > > it a bug? If it is wanted, is there another way to make a connection
> > > outside from an instance method of a Qt::Object-derived object? In C++
> > > (I think) you can write:
> > >
> > > QObject::connect(...)
> > >
> > > In ruby this doesn't work. Is there another way?
> >
> > You need to call connect on the label, not on the button like this:
> >
> > label.connect(btn, SIGNAL('clicked()'), SLOT('clear()'))
> >
> > And C++ is exactly the same.
>
> You're right. I should have checked the Qt documentation before asking, but
> the idea that it could be something like that didn't even cross my mind:
> given you can do sender.connect(SIGNAL(...)){...}, I automatically assumed
> sender.connect was also the correct way to connect signals to slots.
I see, stuff like that really needs documenting properly on the techbase wiki.

> > > * It seems to be impossible to reopen predefined Qt/KDE classes to add
> > > signals and slots to them, even if it is possible to add common
> > > methods. For example, the following works:
> > >
> > > require 'Qt4'
> > >
> > > class Qt::PushButton
> > >   def custom_method
> > >     puts "custom method"
> > >   end
> > > end
> > >
> > > app = Qt::Application.new []
> > > w = Qt::PushButton.new
> > > w.custom_method
> > >
> > > Instead, if I try to add a signal, I get an error when I try to connect
> > > to it:
> > >
> > > require 'Qt4'
> > >
> > > class Qt::PushButton
> > >   signals 'custom_signal()'
> > > end
> > >
> > > app = Qt::Application.new []
> > > w = Qt::PushButton.new
> > > w.connect(SIGNAL('custom_signal()')){puts "custom_signal"}
> > >
> > > The error message is:
> > >
> > > /usr/lib/ruby/site_ruby/1.8/Qt/qtruby4.rb:2706:in `getMetaObject':
> > > undefined method `name' for nil:NilClass (NoMethodError)
> > >         from /usr/lib/ruby/site_ruby/1.8/Qt/qtruby4.rb:2707:in
> > > `getMetaObject' from /usr/lib/ruby/site_ruby/1.8/Qt/qtruby4.rb:2740:in
> > > `metaObject' from /usr/lib/ruby/site_ruby/1.8/Qt/qtruby4.rb:2740:in
> > > `method_missing'
> > >         from /usr/lib/ruby/site_ruby/1.8/Qt/qtruby4.rb:2740:in
> > > `connect' from /usr/lib/ruby/site_ruby/1.8/Qt/qtruby4.rb:2740:in
> > > `signal_connect'
> > >         from prova.rb:9:in `connect'
> > >         from prova.rb:9
> > >
> > > The same seems to happen for slots. Again, is this simply a bug, or it
> > > simply can't be done?
> >
> > It used to be possible, but after I fixed some other bugs the new
> > implementation of the way slots/signals worked with QMetaObjects meant
> > that it is now no longer possible. So I wouldn't say it is a bug, but
> > that former functionality is no longer present. It may be possible to get
> > it working again, but I think adding slots as blocks is a better and more
> > rubyish way to achieve the same thing.
>
> Blocks be used instead of slots, but (as far as I know) not in place of
> signals. I can't say that adding signals to standard classes is a common
> operation, but sometimes it can be useful. For example, I came across this
> issue trying to extend KTextEditor::Document with custom methods and
> instance variables. I wanted a signal to be emitted when an instance
> variable was changed, but found out it wasn't possible. Of course, this
> situation is quite exceptional. In most cases, the right thing to do is to
> create a new class subclassing the standard one and add the signal to that.
> In this case, however, I couldn't do that, since I can't instantiate a
> KTextEditor::Document-derived class using Cls.new. In the end, I decided to
> encapsulate the KTextEditor::Document inside a custom class.
OK, I couldn't see the use case for wanting to add signals to classes, but I 
see your point now. I was thinking about adding custom signals and slots to 
object-specific classes. For example:

# doc is an instance of KTextEditor::Document
class mydoc <<doc
  slots :myslot
  signals :mysig

  def myslot
    emit mysig
  end
  ...
end

But I'm less keen on just adding the custom slots and signals to 
KTextEditor::Document itself as it makes the underlying QMetaObject heirarchy 
look strange and not match the C++ one.

-- Richard



More information about the Kde-bindings mailing list