views:

289

answers:

4

In a quest for handling events (like mouse moves and clicks) not by subclassing, one has to use installEventFilter and provide an event handler. While doing so, I've encountered a problem with RTTI support, meaning that typeid().name() gives QObject * all the time, no matter on which object event was triggered. There is, of course, another solution---dynamic_cast followed by null-pointer check, but personally I don't find it clean (and would like to avoid multiple such checks). To be more specific, here is an example I didn't make to work with Visual C++ with RTTI enabled (/GR):

bool
MousePressInterface::eventFilter
    (QObject *obj,
    QEvent *event)
{
    if (event->type() == QEvent::MouseButtonPress)
    {
     ColorPicker *sender;
     sender = dynamic_cast<ColorPicker *> (obj);

     if ( sender )
     {
      QColor newColor = 
       QColorDialog::getColor(sender->color());
      if ( newColor.isValid() )
                        sender->setColor( newColor );
      Logger::log("color picker clicked");
      return true;
     }
/* TODO: cleaner way, doesn't work for some reason!
     Logger::log(QString("mouse pressed on %1").arg(typeid(obj).name()));
     Logger::log(QString(" checking for %1").arg(typeid(ColorPicker *).name()));

     if ( typeid(obj) == typeid(ColorPicker * ) )
      Logger::log("color picker clicked");
*/
    }
A: 

You should normally use typeid on the dereference of a pointer - the typeid of a pointer is calculated at compile time and is not normally interesting.

if ( typeid(*obj) == typeid(ColorPicker) )
  Logger::log("color picker clicked");

That said, there isn't much difference between what you are doing here, and the dynamic_cast route - in any case you will have to do dynamic_cast at some point.

1800 INFORMATION
yes, I've tried it that way too.Why do I prefer `typeid` way is that you can get .name() as a string and then it's only string comparisons for all the cases I want to handle, not casts again...
MadH
+2  A: 

Use qobject_cast and/or obj->metaObject()->className() instead.

Intransigent Parsnip
thanks! that's exactly what I was looking for!
MadH
+1  A: 

I would use

if (obj->metaObject() == &ColorPicker::staticMetaObject) {
 ...
}

if only ColorPicker-instances (and not subclasses of ColorPicker) is be accepted.

If you are accepting subclasses too, use

if (qobject_cast<ColorPicker *>(obj)) {
  ...
}
larsm
+1  A: 

The pointer must be dereferenced so that the object it points to is used. Without dereferencing the pointer, the result will be the type_info for the pointer, not what it points to.

Logger::log(QString("mouse pressed on %1").arg(typeid(*obj).name()));
TimW