Reputation: 19477
I wanted to create a QObservableCollection
wrapper around a QList
(using an internal QList
for implementation and forwarding all calls while emiting some sort of CollectionsChanged signal for functions that change the collection), but I see that QList
does not inherit from QObject
.
I believe you need to inherit from QObject
to emit Qt Signals. So I'd need to inherit from QObject
for my QObeservableCollection.
But QList
and QVector
and the other Qt collections doen't inherit from QObject
, so I imagine their must be some sort of downside or problem making a collection.
I see that QSignalSpy inherits from both QObject
and QList<QList<QVariant>>
so maybe they just didn't see a reason to inherit from QObject?
Upvotes: 3
Views: 1531
Reputation: 98425
It is certainly not true that you need to be a QObject
to emit signals. All you need is there to be a QObject
somewhere that emits the signals for you. If you want your class to be directly passable to QObject::connect
, your class should provide a conversion operator to QObject*
that returns the pointer to such a proxy object. This completely sidesteps the whole no-templates-with-moc brouhaha.
class FrobinatorObject : public QObject {
Q_OBJECT
Q_SIGNAL void frobSignal();
...
};
template <typename T> class Frobinator {
QScopedPointer<FrobinatorObject> m_proxy;
// Could be a QSharedPointer, depending on what semantics we want
...
public:
operator FrobinatorObject*() const { return m_proxy.data(); }
};
...
Frobinator<int> frob;
QObject::connect(frob, SIGNAL(frobSignal()), ...);
// or
QObject::connect(frob, &FrobinatorObject::frobSignal, ...);
Also note that while it's true that you can't have signals nor slots in a template-parametrized class, you can certainly have them in a base class that you then derive from. The base class can deal with type-deleted arguments. So:
// This won't work
template <typename T> class TemplateClass : public QObject {
Q_OBJECT
Q_SLOT void aSlot(const T *);
...
};
// But this certainly does work
class BaseClass : public QObject {
Q_OBJECT
Q_SLOT void aSlot(const void *);
...
}
template <typename T> class TemplateClass : public BaseClass {
void aMethod(const T * t) {
BaseClass::aSlot((const void*)&t);
}
...
}
The TemplateClass
can also dynamically add slots of the correct type signature to the BaseClass
. While that requires some understanding of Qt's internals, it can certainly be done for a class that's supposed to be a reusable, framework-style class.
Upvotes: 3
Reputation: 37607
Reason is simple containers are like values, you have assign operator, you can copy them clone and so on.
QObject
s can't have such functionality, they are not copyable. Try imagine what should happen when you creating clone of object with connected slots and signals. It will lead to total mess. And what should happen with children of cloned object? Should be also cloned?
Another thing is templates usage. Class template which is a QObject
is real problem for moc a tool.
Upvotes: 3
Reputation: 48196
QList is meant to be a value type (like std::vector
) which uses implicit sharing while QObjects must be used as pointers and disallow copying
there are other classes which mirror this use such as QImage
Upvotes: 4
Reputation: 27611
The extra overhead in inheriting from QObject is unnecessary for the majority of uses. Containers should be as small and as fast as possible.
If you wanted to inherit from QList and provide that functionality for a class of your own, you can do that.
Upvotes: 1
Reputation: 22346
There is a very important technical reason: The moc
cannot handle templates, which is pretty much a necessity for a generic container type.
Upvotes: 5
Reputation: 20030
While I can't look into the minds of the developers, I would say that there's simply no need. A QList is a simple container. It should hold elements, allow for their addition or removal, iteration over them, etc.
It does not need a parent or children. There's no immediate need for signals or slots. It's a matter of keeping things simple.
If you do indeed require additional functionality beyond what a QList provides, it's easy enough to implement. But as for a general case, I guess it's a reasonable and logical decision to not overcomplicate things.
Upvotes: 2