[PyQt] Proposal for New-style Signals
digulla at hepe.com
Wed Jan 23 17:00:33 GMT 2008
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:
> In addition, for signal overloads with no arguments (ie. with '' as the signal
> key) the index can be omitted as follows:
Just for reference, here all the other options:
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?").
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
> 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:
OTOH, how many signals are there which *use* overloading? 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?), 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.
Aaron "Optimizer" Digulla a.k.a. Philmann Dark
"It's not the universe that's limited, it's our imagination.
Follow me and I'll show you something beyond the limits."
More information about the PyQt