[Qt-interest] connect()ing multiple buttons to a receiver

Malyushytsky, Alex alex at wai.com
Fri Jan 9 05:30:21 CET 2009


>> Imagine what would happen if anyone would connect any *other* object's signal (other than from a QButton!) to your slot: Your code above would

Referenced code has not being meant even to be a perfect C++  (normally I would use static_cast or dynamic_cast instead of (QButton*) for example) or QT code (there is no such class as QButton in QT4 I believe) or provide a way to insure safety. Irrelevant to the question asked or situational checks were omitted to make answer easier to understand.

The purpose of the code was to demonstrate how to locate which object sent a signal, cause person who asked the question said : "I know about QObject::sender(), but I still don't know of how to tell *which* button it points to at that point." That what it did I believe.

>>Again: for quick'n'dirty code or code which is used just very "locally" in a large application it might be okay to use sender(). But I would refrain from using sender() if the slot was public or protected and you could never foretell what other code will call it (maybe in 2 years away from now...).

I disagree that usage of sender() is "dirty" or unsafe. It does not matter, if slot is protected, public or private.

Any code is as safe, as you make it.
All arguments mentioned about unsafe usage of sender() are related to the safety of pointer usage. If you deal with C++, you deal with pointers and have to understand how to make their usage safe.

In general usage of QSignalMapper is as safe as usage of sender().
If you QSignalMapper is used, in a slot called as a reaction on a signal QSignalMapper::mapped ( QObject * object ), exactly the same pointer checks are required as after sender() call.

If it was unclear what checks are required I would recommend:
1) Use Q_ASSERT to check condition to help debug expected conditions:
Q_ASSERT( sender()->inherits("QAbstractButton");

2) If you have pointer to QObject, use inherits() or qobject_cast

QObject* s= sender();
if ( s )
{
   if (s ->inherits("QComboBox") )   {  .....
   }
   else if (s->inherits("QAbstractButton")   {  .....
   }
   else
     Q_ASSERT(false);
}
Usage inherits() not only provides the safety check, but also allows slot to handle different clases as a sender.

3)If you have a pointer not derived from QObject use static_cast or dynamic_cast. Last is preferable, but can be used only if Run-Time Type info is enabled in your project.

Conclusion:
QT itself is using sender() and there is nothing wrong for anybody else to use it. It is a part of the official API and is as safe as using pointers in general.  Even referenced QT4 documentation says:
>>"However, getting access to the sender might be useful when many signals are connected to a single slot."

I don't want to push anybody to a specific decision. I would say that using sender() in my cases leaded to the simpler and faster code, but I might chose different solution in other case.

I would recommend do not make decisions based on incorrect arguments. Also QSignalMapper is limited to parameterless signals, so it is good to know about sender() anyway.

Best regards,
   Alex



-----Original Message-----
From: qt-interest-bounces at trolltech.com [mailto:qt-interest-bounces at trolltech.com] On Behalf Of Oliver.Knoll at comit.ch
Sent: Thursday, January 08, 2009 12:17 AM
To: qt-interest at trolltech.com
Subject: Re: [Qt-interest] connect()ing multiple buttons to a receiver

Malyushytsky, Alex wrote on Wednesday, January 07, 2009 11:32 PM:

> ...
> If this slot can be invoked only from clicking on QButton you could:
>
> if ( sender() )
> {
> QButton* b = (QButton*) sender();
>  .....
>
> }

While this works in practice it is dangerous and for good reason the Qt docs discourage you to use the sender() method:

http://doc.trolltech.com/4.4/qobject.html#sender
"Warning: This function violates the object-oriented principle of modularity. However, getting access to the sender might be useful when many signals are connected to a single slot."

Imagine what would happen if anyone would connect any *other* object's signal (other than from a QButton!) to your slot: Your code above would miserably die with an invalid cast. In your slot you *implicitly* assume that *every* sender is a QButton (again, in practice for quick'n'dirty code this assumption is often okay).

QSignalMapper seems to be a bit more cumbersome, but it makes it explicit what you are actually trying to achieve. And it works with *any* sender (as long as you assign them unique IDs). The other solution which has been proposed (using QButtonGroup) is basically the same idea: it is a "QSignalMapper specialised for QAbstractButtons".

  http://doc.trolltech.com/4.4/qbuttongroup.html#addButton-2
  http://doc.trolltech.com/4.4/qbuttongroup.html#buttonClicked-2


Cheers, Oliver
--
Oliver Knoll
Dipl. Informatik-Ing. ETH
COMIT AG - ++41 79 520 95 22

_______________________________________________
Qt-interest mailing list
Qt-interest at trolltech.com
http://lists.trolltech.com/mailman/listinfo/qt-interest


---------------------------------------------------------------------------------------------------
Weidlinger Associates, Inc. made the following annotations.

"This message and any attachments are solely for the intended recipient and may contain confidential or privileged information. If you are not the intended recipient, any disclosure, copying, use, or distribution of the information included in this message and any attachments is prohibited. If you have received this communication in error, please notify us by reply e-mail and immediately and permanently delete this message and any attachments. Thank you."

"Please consider our environment before printing this email."




More information about the Qt-interest-old mailing list