[PyQt] Proposal for New-style Signals

Phil Thompson phil at riverbankcomputing.com
Thu Jan 24 10:09:40 GMT 2008


On Wednesday 23 January 2008, Aaron Digulla wrote:
> Phil Thompson schrieb:
> > Signals are passed to QObject's [dis]connect() and emit() methods. 
> > Currently, If the signal is invalid then no indication is provided to
> > that effect.  If a simple string is used instead of SIGNAL() then an
> > invalid Qt signal will cause a Python exception to be raised.
>
> Good. That means people like me can define constants for the strings and
> use them to get auto completion and we both get typo safety.
>
> >  As now, an "invalid" short-circuit
> > signal will not cause an exception to be raised.
> >
> :/ See below.
> :
> > Question: It would be possible to allow (but not require) short-circuit
> > signals to be predefined using __pyqtSignals__.  [dis]connect() and
> > emit() could then check the name (but not any arguments) of the signal. 
> > A check would only fail if at least one short-circuit signal had been
> > defined (to preserve backwards compatibility).  Is this worthwhile?  (My
> > feeling is no.)
>
> How much effort would it be? I always predefine all my signals because I
> make so many typos, so a way which would allow me to check them might be
> good. OTOH, since I always use the predefined constant, I always have
> the same typo in all places, so it doesn't really matter for me.
>
> It would just make life more simple for people who make many typos and
> don't use constants. They are unlikely to predefine their signals,
> either, I guess.
>
> > The Qt signals with a particular name will be represented by a new signal
> > object stored as a class attribute.  Individual signals (ie. with a
> > particular signature) will be accessed as an index using a string
> > containing a comma separated list of argument types as the key.
> >
> > Each individual signal will have [dis]connect() and emit() methods.
> >
> > For example:
> >
> >     btn.clicked[''].connect(self.on_clicked)
> >     btn.clicked['bool'].connect(self.on_clicked_checked)
> >
> >     btn.toggled['bool'].emit(True)
> >
> > In addition, for signal overloads with no arguments (ie. with '' as the
> > signal key) the index can be omitted as follows:
> >
> >     btn.clicked.connect(self.on_clicked)
>
> Just for reference, here all the other options:
>
>     btn.clicked.connect(self.on_clicked) [A]
>     self.connect(btn.clicked, self.on_clicked) [B]
>     Qt.connect(btn.clicked, self.on_clicked) [C]
>     connect(btn.clicked, self.on_clicked) [D]
>
> A is your proposal, B is more like what we have today, C would allow
> variant D for lazy developers. B is longer than A and it somehow links
> "connect" to "self" which confuses people in todays API ("do I use
> 'self.connect(btn' or 'btn.connect(btn' or what? What's the difference?").

B, C and D are the same. The difference is how you imported the connect() 
function.

> So A would be my favorite, too, especially with auto completion. I'm not
> happy with the index syntax but I have absolutely no idea how to solve
> that any other way. It's just hell to type :( Will it be possible to say:
>
>     QPushButton.clickedBool = QPushButton.clicked['bool']
>
> ? I.e. when I often need a specific connector, can I define my own
> shortcuts?

Yes.

> > Note that for a signal with at least one argument, but without an
> > overload that has no arguments, this "short form" is invalid.  This is to
> > allow for the addition of a no-argument overload some time in the future.
>
> I agree with your argument but I don't like it. See below.
>
> > Question: An alternative approach would be to define a "default" signal
> > (in the .sip files) which would identify the overload to be used with the
> > "short form".  As most Qt signals aren't overloaded this would mean that
> > the type string would not have to be specified in the majority of cases. 
> > Is this worthwhile? (My feeling is yes.)
>
> I'd even go as far as asking to allow developers to change the "default"
> signal but a default signal is a must have. There are so many widgets
> which emit complex signals with many arguments while there is just one
> version of the signal and having to type all those strings all the time
> ... ugh. ;)
>
> > The signal names (but not the types) will be included in the API file for
> > code completion support.
>
> Can you do a quick grep/cut/sort/uniq/wc on the SIP sources to check how
> many different type strings there would be? I have a feeling that there
> won't be that many ("bool", "int", "QString" and "QModelIndex" should
> cover 60-80%?) If so, how about:
>
>     btn.clicked.bool.connect(self.on_clicked_checked)

I've already explained why any new approach will stick with strings.

> OTOH, how many signals are there which *use* overloading?

Of 317 signals, 13 have overloads.

> Okay, we have 
> to support a way to handle these corner cases but if there aren't any
> examples in the Qt API, scrap my comment. In that case, just use make
> the currently defined signal (no matter how complex their argument lists
> are) the default.
>
> Later if a non-argument signal would ever be defined (and how likely is
> that?), 

It doesn't matter how likely it is, the point is that it's possible.

> you could always access it with "widget.signal['']". Plus Python 
> will start to complain when the signal is invoked since the argument
> lists probably don't match anymore, so there is little chance that such
> a change would go unnoticed forever.

Phil


More information about the PyQt mailing list