Show us the slot please.
high_flyer: Yes I'm 100% sure, stepped through it a few times already. I've added the assert like this:
Qt Code:
Q_ASSERT(obj); 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:
// The declaration: private slots: // The implementation: // Rebuild the tree structure: reset(); deleteRootItem(); QVector<QVariant> columns; d->rootItem = new ObserverTreeItem(0,0,columns); d->rootItem->setObjectName("Root Item"); ObserverTreeItem* top_level_observer_item = new ObserverTreeItem(d_observer,d->rootItem); d->rootItem->appendChild(top_level_observer_item); setupChildData(top_level_observer_item); //printStructure(); emit layoutAboutToBeChanged(); emit layoutChanged(); // Handle item selection after tree has been rebuilt: if (new_focus) { QList<QObject*> objects; objects << new_focus; emit selectObjects(objects); } else if (d->selected_objects.count() > 0) emit selectObjects(d->selected_objects); else emit selectObjects(QList<QObject*>()); }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
Yes, if the slot is private other classes signals can not access it.I'm wondering if it makes a difference that the slot is private since the signal and slot is on different objects
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.
Unfortunately they can. Not direct, but through the meta object, it is possible. Unfortunately.Qt Code:
#include <QtGui> { Q_OBJECT private Q_SLOTS: void killAll() { qWarning() << Q_FUNC_INFO; qApp->quit(); } }; int main(int argc, char *argv[]) { QTimer t; t.setSingleShot(true); t.setInterval(1000); Test o; // o.killAll(); fails t.start(); return app.exec(); } #include "main.moc"To copy to clipboard, switch view to plain text mode
?// 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.
Addendum: Thus you can also easily substitute the non working direct call with QMetaObject::invokeMethod() and break the encapsulation.
Ok, I've made the slot public and rebuilt. Still I get a null everytime.
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.
And the classes are also not related (through derivation) (just making sure)the signal and slot are on different classes.
==========================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.
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:
{ if (_id < 0) return _id; switch (_id) { case 0: modificationStateChanged((*reinterpret_cast< bool(*)>(_a[1]))); break; case 1: monitoredPropertyChanged((*reinterpret_cast< const char*(*)>(_a[1])),(*reinterpret_cast< QList<QObject*>(*)>(_a[2]))); break; case 2: monitoredPropertyChanged((*reinterpret_cast< const char*(*)>(_a[1]))); break; case 3: propertyChangeFiltered((*reinterpret_cast< const char*(*)>(_a[1])),(*reinterpret_cast< QList<QObject*>(*)>(_a[2]))); break; case 4: propertyChangeFiltered((*reinterpret_cast< const char*(*)>(_a[1]))); break; case 5: numberOfSubjectsChanged((*reinterpret_cast< Observer::SubjectChangeIndication(*)>(_a[1])),(*reinterpret_cast< QList<QObject*>(*)>(_a[2]))); break; case 6: numberOfSubjectsChanged((*reinterpret_cast< Observer::SubjectChangeIndication(*)>(_a[1]))); break; case 8: layoutChanged(); break; default: ; }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:
{ _id = Observer::qt_metacall(_c, _id, _a); if (_id < 0) 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.
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!The class emitting the signal is called Observer. The instance on which the signal is emitted is called TreeNode which inherits Observer.
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:
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...Qt Code:
To copy to clipboard, switch view to plain text mode
==========================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.
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.
Ok no problem let me explain in more detail:
Qt Code:
// 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. { Q_OBJECT public: Observer(); virtual ~Observer(); void someFunctionEmittingTheSignal() { emit layoutChanged(new_obj); } signals: } // This is the class of which the instance is created: class TreeNode: public Observer { Q_OBJECT public: TreeNode(); virtual ~TreeNode(); }To copy to clipboard, switch view to plain text mode
I have another class with the slot (again simplified):
Qt Code:
// This is the class of which the instance is created: { Q_OBJECT public: ObserverTreeModel(); virtual ~ObserverTreeModel(); setObserverContext(Observer* obs) { d_observer = obs; } private slots: void rebuildTreeStructure(Object* obj = 0) { // Do some stuff that is going to change the layout of the tree. emit layoutAboutToChange(); // Emits QAbstractItemModel::layoutAboutToChange(); emit layoutChanged(); // Emits QAbstractItemModel::layoutChanged(); } private: Observer* d_observer; }To copy to clipboard, switch view to plain text mode
I do something like this then:
Qt Code:
ObserverTreeModel model; TreeNode tree_node; model.setObserverContext(&tree_node); tree_node.someFunctionEmittingTheSignal();To copy to clipboard, switch view to plain text mode
I hope that explains it better.
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.
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?
Bookmarks