Page 1 of 2 12 LastLast
Results 1 to 20 of 22

Thread: Struggling with signal which has a default parameter.

  1. #1
    Join Date
    Aug 2008
    Posts
    132
    Thanks
    23
    Thanked 3 Times in 3 Posts

    Default Struggling with signal which has a default parameter.

    Hi

    I'm really struggling with a signal which has a default parameter. Here is the way I declare the signal and slot:
    Qt Code:
    1. // Signal declaration:
    2. signals:
    3. void layoutChanged(QObject* added_object = 0);
    4.  
    5. // Slot declaration:
    6. public slots:
    7. void rebuildTreeStructure(QObject* new_focus = 0);
    To copy to clipboard, switch view to plain text mode 

    And I connect it to a slot as follows:
    Qt Code:
    1. connect(d_observer,SIGNAL(layoutChanged(QObject*)),SLOT(rebuildTreeStructure(QObject*)));
    To copy to clipboard, switch view to plain text mode 

    Then for whatever reason I emit the signal with a valid QObject reference and I always get a null in the slot. I've been trying to debug this for ages and found the following:

    - Looking at the _moc file of the class emitting the signal I see that it calls it correctly and the _t1 parameter is valid during debugging:

    Qt Code:
    1. // SIGNAL 7
    2. void Qtilities::Core::Observer::layoutChanged(QObject * _t1)
    3. {
    4. void *_a[] = { 0, const_cast<void*>(reinterpret_cast<const void*>(&_t1)) };
    5. QMetaObject::activate(this, &staticMetaObject, 7, _a);
    6. }
    To copy to clipboard, switch view to plain text mode 

    Going through the stack I see that qt_metalcall is called with the wrong argument (or it looks like it). This function is called with _id = 8, which is the signal with its default parameter.

    Qt Code:
    1. int Qtilities::Core::Observer::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
    2. {
    3. _id = QObject::qt_metacall(_c, _id, _a);
    4. if (_id < 0)
    5. return _id;
    6. if (_c == QMetaObject::InvokeMetaMethod) {
    7. switch (_id) {
    8. case 0: modificationStateChanged((*reinterpret_cast< bool(*)>(_a[1]))); break;
    9. case 1: monitoredPropertyChanged((*reinterpret_cast< const char*(*)>(_a[1])),(*reinterpret_cast< QList<QObject*>(*)>(_a[2]))); break;
    10. case 2: monitoredPropertyChanged((*reinterpret_cast< const char*(*)>(_a[1]))); break;
    11. case 3: propertyChangeFiltered((*reinterpret_cast< const char*(*)>(_a[1])),(*reinterpret_cast< QList<QObject*>(*)>(_a[2]))); break;
    12. case 4: propertyChangeFiltered((*reinterpret_cast< const char*(*)>(_a[1]))); break;
    13. case 5: numberOfSubjectsChanged((*reinterpret_cast< Observer::SubjectChangeIndication(*)>(_a[1])),(*reinterpret_cast< QList<QObject*>(*)>(_a[2]))); break;
    14. case 6: numberOfSubjectsChanged((*reinterpret_cast< Observer::SubjectChangeIndication(*)>(_a[1]))); break;
    15. case 7: layoutChanged((*reinterpret_cast< QObject*(*)>(_a[1]))); break;
    16. case 8: layoutChanged(); break;
    17. default: ;
    18. }
    To copy to clipboard, switch view to plain text mode 

    Maybe I'm missing something simple. Any inputs will be appreciated.
    Thanks,
    Jaco

  2. #2
    Join Date
    Jan 2006
    Location
    Munich, Germany
    Posts
    4,714
    Thanks
    21
    Thanked 418 Times in 411 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: Struggling with signal which has a default parameter.

    Did you clean/rebuild?
    ==========================signature=============== ==================
    S.O.L.I.D principles (use them!):
    https://en.wikipedia.org/wiki/SOLID_...iented_design)

    Do you write clean code? - if you are TDD'ing then maybe, if not, your not writing clean code.

  3. #3
    Join Date
    Aug 2008
    Posts
    132
    Thanks
    23
    Thanked 3 Times in 3 Posts

    Default Re: Struggling with signal which has a default parameter.

    Hi

    I've rebuilt it a few times. Have not cleaned but as far as I'm aware Creator cleans in any case during a rebuild. I've now made the slot's parameter not to have a default but that still does not solve anything. Also reading the "Signals And Slots With Default Arguments" part of the docs another time does not shed any light on this.

    Any ideas?
    Thanks,
    Jaco

  4. #4
    Join Date
    Jan 2006
    Location
    Munich, Germany
    Posts
    4,714
    Thanks
    21
    Thanked 418 Times in 411 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: Struggling with signal which has a default parameter.

    Then for whatever reason I emit the signal with a valid QObject reference and I always get a null in the slot.
    Are you sure?
    Make an assertion there (just before emitting), to be sure.
    ==========================signature=============== ==================
    S.O.L.I.D principles (use them!):
    https://en.wikipedia.org/wiki/SOLID_...iented_design)

    Do you write clean code? - if you are TDD'ing then maybe, if not, your not writing clean code.

  5. #5
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Struggling with signal which has a default parameter.

    Show us the slot please.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  6. #6
    Join Date
    Aug 2008
    Posts
    132
    Thanks
    23
    Thanked 3 Times in 3 Posts

    Default Re: Struggling with signal which has a default parameter.

    high_flyer: Yes I'm 100% sure, stepped through it a few times already. I've added the assert like this:

    Qt Code:
    1. Q_ASSERT(obj);
    2. emit layoutChanged(obj);
    To copy to clipboard, switch view to plain text mode 

    Also obj is declared QObject*, its not a QPointer which might have become zero for some reason, although I'm sure this is not happening.

    wysota: Here is the slot's declaration and implementation:
    Qt Code:
    1. // The declaration:
    2. private slots:
    3. void rebuildTreeStructure(QObject* new_focus = 0);
    4.  
    5. // The implementation:
    6. void Qtilities::CoreGui::ObserverTreeModel::rebuildTreeStructure(QObject* new_focus) {
    7. // Rebuild the tree structure:
    8. QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
    9. reset();
    10. deleteRootItem();
    11. QVector<QVariant> columns;
    12. columns.push_back(QString("Child Count"));
    13. columns.push_back(QString("Access"));
    14. columns.push_back(QString("Type Info"));
    15. columns.push_back(QString("Object Tree"));
    16. d->rootItem = new ObserverTreeItem(0,0,columns);
    17. d->rootItem->setObjectName("Root Item");
    18. ObserverTreeItem* top_level_observer_item = new ObserverTreeItem(d_observer,d->rootItem);
    19. d->rootItem->appendChild(top_level_observer_item);
    20. setupChildData(top_level_observer_item);
    21. //printStructure();
    22. emit layoutAboutToBeChanged();
    23. emit layoutChanged();
    24.  
    25. // Handle item selection after tree has been rebuilt:
    26. if (new_focus) {
    27. QList<QObject*> objects;
    28. objects << new_focus;
    29. emit selectObjects(objects);
    30. } else if (d->selected_objects.count() > 0)
    31. emit selectObjects(d->selected_objects);
    32. else
    33. emit selectObjects(QList<QObject*>());
    34.  
    35. QApplication::restoreOverrideCursor();
    36. }
    To copy to clipboard, switch view to plain text mode 

    I'm wondering if it makes a difference that the slot is private since the signal and slot is on different objects. I did however changed it to public now and it did not work either however I'm still doing a rebuild all on it to double check.

    Thanks,
    Jaco

  7. #7
    Join Date
    Jan 2006
    Location
    Munich, Germany
    Posts
    4,714
    Thanks
    21
    Thanked 418 Times in 411 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: Struggling with signal which has a default parameter.

    I'm wondering if it makes a difference that the slot is private since the signal and slot is on different objects
    Yes, if the slot is private other classes signals can not access it.

    From a brief look I see you are emitting layoutChanged() from your slot, and that one is with a default value, which would explain why in the debugger you see first the one with a non NULL object, and then one with NULL.
    You have a recursion there.
    ==========================signature=============== ==================
    S.O.L.I.D principles (use them!):
    https://en.wikipedia.org/wiki/SOLID_...iented_design)

    Do you write clean code? - if you are TDD'ing then maybe, if not, your not writing clean code.

  8. #8
    Join Date
    Jan 2006
    Location
    Germany
    Posts
    4,380
    Thanks
    19
    Thanked 1,005 Times in 913 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows Symbian S60
    Wiki edits
    5

    Default Re: Struggling with signal which has a default parameter.

    Quote Originally Posted by high_flyer View Post
    Yes, if the slot is private other classes signals can not access it.
    Unfortunately they can. Not direct, but through the meta object, it is possible. Unfortunately.
    Qt Code:
    1. #include <QtGui>
    2.  
    3. class Test : public QWidget
    4. {
    5. Q_OBJECT
    6. private Q_SLOTS:
    7. void killAll()
    8. {
    9. qWarning() << Q_FUNC_INFO;
    10. qApp->quit();
    11. }
    12. };
    13.  
    14.  
    15. int main(int argc, char *argv[])
    16. {
    17. QApplication app(argc, argv);
    18.  
    19. QTimer t;
    20. t.setSingleShot(true);
    21. t.setInterval(1000);
    22.  
    23. Test o;
    24. QObject::connect(&t, SIGNAL(timeout()), &o, SLOT(killAll()));
    25.  
    26. // o.killAll(); fails
    27. t.start();
    28. return app.exec();
    29. }
    30.  
    31. #include "main.moc"
    To copy to clipboard, switch view to plain text mode 

  9. #9
    Join Date
    Jan 2006
    Location
    Munich, Germany
    Posts
    4,714
    Thanks
    21
    Thanked 418 Times in 411 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: Struggling with signal which has a default parameter.

    // o.killAll(); fails
    ?
    So if it fails it means the slot is not accessible... oder?

    EDIT:
    Oh, I get you now, you mean a direct call fails, but the signals/slot connection works.
    Ok.

    Thanks for the heads up!
    Interesting...
    ==========================signature=============== ==================
    S.O.L.I.D principles (use them!):
    https://en.wikipedia.org/wiki/SOLID_...iented_design)

    Do you write clean code? - if you are TDD'ing then maybe, if not, your not writing clean code.

  10. #10
    Join Date
    Jan 2006
    Location
    Germany
    Posts
    4,380
    Thanks
    19
    Thanked 1,005 Times in 913 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows Symbian S60
    Wiki edits
    5

    Default Re: Struggling with signal which has a default parameter.

    Addendum: Thus you can also easily substitute the non working direct call with QMetaObject::invokeMethod() and break the encapsulation.

  11. #11
    Join Date
    Aug 2008
    Posts
    132
    Thanks
    23
    Thanked 3 Times in 3 Posts

    Default Re: Struggling with signal which has a default parameter.

    Ok, I've made the slot public and rebuilt. Still I get a null everytime.

    Quote Originally Posted by high_flyer View Post
    From a brief look I see you are emitting layoutChanged() from your slot, and that one is with a default value, which would explain why in the debugger you see first the one with a non NULL object, and then one with NULL.
    You have a recursion there.
    I did mention it but probably not clear enough, the signal and slot are on different classes. Thus the layoutChanged() I emit in the slot is not the same, it is layoutChanged() on QAbstractItemModel.

  12. #12
    Join Date
    Jan 2006
    Location
    Munich, Germany
    Posts
    4,714
    Thanks
    21
    Thanked 418 Times in 411 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: Struggling with signal which has a default parameter.

    the signal and slot are on different classes.
    And the classes are also not related (through derivation) (just making sure)
    ==========================signature=============== ==================
    S.O.L.I.D principles (use them!):
    https://en.wikipedia.org/wiki/SOLID_...iented_design)

    Do you write clean code? - if you are TDD'ing then maybe, if not, your not writing clean code.

  13. #13
    Join Date
    Aug 2008
    Posts
    132
    Thanks
    23
    Thanked 3 Times in 3 Posts

    Default Re: Struggling with signal which has a default parameter.

    Yes they are not related. I've checked that it only breaks once in that function as well.

    As I said in my first post, it looks like the wrong signal is emitted by the meta object system.

    Qt Code:
    1. int Qtilities::Core::Observer::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
    2. {
    3. _id = QObject::qt_metacall(_c, _id, _a);
    4. if (_id < 0)
    5. return _id;
    6. if (_c == QMetaObject::InvokeMetaMethod) {
    7. switch (_id) {
    8. case 0: modificationStateChanged((*reinterpret_cast< bool(*)>(_a[1]))); break;
    9. case 1: monitoredPropertyChanged((*reinterpret_cast< const char*(*)>(_a[1])),(*reinterpret_cast< QList<QObject*>(*)>(_a[2]))); break;
    10. case 2: monitoredPropertyChanged((*reinterpret_cast< const char*(*)>(_a[1]))); break;
    11. case 3: propertyChangeFiltered((*reinterpret_cast< const char*(*)>(_a[1])),(*reinterpret_cast< QList<QObject*>(*)>(_a[2]))); break;
    12. case 4: propertyChangeFiltered((*reinterpret_cast< const char*(*)>(_a[1]))); break;
    13. case 5: numberOfSubjectsChanged((*reinterpret_cast< Observer::SubjectChangeIndication(*)>(_a[1])),(*reinterpret_cast< QList<QObject*>(*)>(_a[2]))); break;
    14. case 6: numberOfSubjectsChanged((*reinterpret_cast< Observer::SubjectChangeIndication(*)>(_a[1]))); break;
    15. case 7: layoutChanged((*reinterpret_cast< QObject*(*)>(_a[1]))); break;
    16. case 8: layoutChanged(); break;
    17. default: ;
    18. }
    To copy to clipboard, switch view to plain text mode 

    As I said, the debugger steps into case 8 in the above code so I'm pretty sure the problem is with the delivery of the signal, rather than the receiving side. At least it looks like that.

    One thing I don't understand is the following:
    The class emitting the signal is called Observer. The instance on which the signal is emitted is called TreeNode which inherits Observer. Stepping through the debugger the signal emission goes into the qt_metacall function of TreeNode and then basically calls qt_metacall on the Observer base class. This is the piece of code I'm referring to:

    Qt Code:
    1. int Qtilities::CoreGui::TreeNode::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
    2. {
    3. _id = Observer::qt_metacall(_c, _id, _a);
    4. if (_id < 0)
    5. return _id;
    To copy to clipboard, switch view to plain text mode 

    The above funciton is entered with _id = 12, however as soon as it steps into the base class observer the base class gets _id = 8 as the parameter which is the signal with the default argument. Maybe I don't know the moc system that well and its correct but it does not make sense to me.

  14. #14
    Join Date
    Jan 2006
    Location
    Munich, Germany
    Posts
    4,714
    Thanks
    21
    Thanked 418 Times in 411 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: Struggling with signal which has a default parameter.

    The class emitting the signal is called Observer. The instance on which the signal is emitted is called TreeNode which inherits Observer.
    I don't understand this - the instance should BE Objserver instance, not inherit it - which would mean its an instance of a class that inherits Observer - can you clarify this - since if this is confused, it can well be the root of the problem!

    Lets try to do this in order:
    What object (which class is it, what is its instance (variable/obejct) name?
    What object declares and implements the slot?

    based on your original post:
    Qt Code:
    1. connect(d_observer,SIGNAL(layoutChanged(QObject*)),SLOT(rebuildTreeStructure(QObject*)));
    To copy to clipboard, switch view to plain text mode 
    The sender class and instance is also the slot class and instance, and in the slot you are emitting the same signal again, even though you said its another class...
    ==========================signature=============== ==================
    S.O.L.I.D principles (use them!):
    https://en.wikipedia.org/wiki/SOLID_...iented_design)

    Do you write clean code? - if you are TDD'ing then maybe, if not, your not writing clean code.

  15. #15
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Struggling with signal which has a default parameter.

    Change the name of the signal and the slot to something not clashing with existing signals in Qt. You can also try declaring two separate slots - one with the QObject param and the other without it and see if it changes anything. It could be that moc has a bug somewhere that makes it work incorrectly with slots that have default params.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  16. #16
    Join Date
    Aug 2008
    Posts
    132
    Thanks
    23
    Thanked 3 Times in 3 Posts

    Default Re: Struggling with signal which has a default parameter.

    Ok no problem let me explain in more detail:

    Qt Code:
    1. // This is a simplified view of the observer class which contains the signal. The signal is also emitted in one of this class's functions.
    2. class Observer : public QObject
    3. {
    4. Q_OBJECT
    5.  
    6. public:
    7. Observer();
    8. virtual ~Observer();
    9.  
    10. void someFunctionEmittingTheSignal() {
    11. QObject* new_obj = new QObject();
    12. emit layoutChanged(new_obj);
    13. }
    14.  
    15. signals:
    16. void layoutChanged(QObject* added_object = 0);
    17.  
    18. }
    19.  
    20. // This is the class of which the instance is created:
    21. class TreeNode: public Observer
    22. {
    23. Q_OBJECT
    24.  
    25. public:
    26. TreeNode();
    27. virtual ~TreeNode();
    28. }
    To copy to clipboard, switch view to plain text mode 

    I have another class with the slot (again simplified):
    Qt Code:
    1. // This is the class of which the instance is created:
    2. class ObserverTreeModel: public QAbstractItemModel
    3. {
    4. Q_OBJECT
    5.  
    6. public:
    7. ObserverTreeModel();
    8. virtual ~ObserverTreeModel();
    9. setObserverContext(Observer* obs) {
    10. d_observer = obs;
    11. connect(d_observer,SIGNAL(layoutChanged(QObject*)),SLOT(rebuildTreeStructure(QObject*)));
    12. }
    13.  
    14. private slots:
    15. void rebuildTreeStructure(Object* obj = 0) {
    16. // Do some stuff that is going to change the layout of the tree.
    17. emit layoutAboutToChange(); // Emits QAbstractItemModel::layoutAboutToChange();
    18. emit layoutChanged(); // Emits QAbstractItemModel::layoutChanged();
    19. }
    20.  
    21. private:
    22. Observer* d_observer;
    23. }
    To copy to clipboard, switch view to plain text mode 

    I do something like this then:
    Qt Code:
    1. ObserverTreeModel model;
    2. TreeNode tree_node;
    3. model.setObserverContext(&tree_node);
    4. tree_node.someFunctionEmittingTheSignal();
    To copy to clipboard, switch view to plain text mode 

    I hope that explains it better.

    Quote Originally Posted by wysota View Post
    You can also try declaring two separate slots - one with the QObject param and the other without it and see if it changes anything. It could be that moc has a bug somewhere that makes it work incorrectly with slots that have default params.
    I've removed the default parameter on the slots side, but it did not make a difference.
    Last edited by JPNaude; 20th January 2011 at 12:07.

  17. #17
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Struggling with signal which has a default parameter.

    So the only explanation I can see is that your parameter has been deleted somewhere in the meantime. By the way, is line #15 of your last snippet a typo or a real code?
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  18. #18
    Join Date
    Aug 2008
    Posts
    132
    Thanks
    23
    Thanked 3 Times in 3 Posts

    Default Re: Struggling with signal which has a default parameter.

    Quote Originally Posted by wysota View Post
    So the only explanation I can see is that your parameter has been deleted somewhere in the meantime. By the way, is line #15 of your last snippet a typo or a real code?
    I'm very sure that its not deleted because I can access it in the tree view directly after this function. Also if it was a QPointer and it was deleted it would make sense but if it was deleted in my case I should get an invalid pointer.

    Yes that was a typo, thanks.

  19. #19
    Join Date
    Jan 2006
    Location
    Munich, Germany
    Posts
    4,714
    Thanks
    21
    Thanked 418 Times in 411 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: Struggling with signal which has a default parameter.

    Qt Code:
    1. private slots:
    2. void rebuildTreeStructure(Object); //is this a typo? (QObject*)
    To copy to clipboard, switch view to plain text mode 

    EDIT:Oh, to slow with my post...

    Well, try as wysota said to rename the signals and slots to be unique, see if this helps.
    ==========================signature=============== ==================
    S.O.L.I.D principles (use them!):
    https://en.wikipedia.org/wiki/SOLID_...iented_design)

    Do you write clean code? - if you are TDD'ing then maybe, if not, your not writing clean code.

  20. #20
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Struggling with signal which has a default parameter.

    The problem is what you said in post #13 - QMetaObject is stepping into a wrong case. It should go into 7 and not 8. Can you show us all places where you emit this signal? In post #6 there is an emit layoutChanged() but it seems this is a different "layoutChanged()".
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


Similar Threads

  1. Slot - Signal with parameter
    By Lodhart in forum Newbie
    Replies: 8
    Last Post: 10th April 2013, 10:08
  2. Replies: 2
    Last Post: 6th July 2009, 12:53
  3. Replies: 3
    Last Post: 3rd May 2009, 14:15
  4. Struggling with QThread...
    By TemporalBeing in forum Qt Programming
    Replies: 2
    Last Post: 23rd March 2009, 20:46
  5. Struggling with value space
    By UnicycleBloke in forum Qt for Embedded and Mobile
    Replies: 3
    Last Post: 28th May 2008, 23:26

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.