Access QList<T> from qml - c++

I want to access a QList from qml.
Here is a sample code
class A;
class B : public QObject {
...
Q_INVOKABLE QQmlListProperty<A> read();
...
private:
QList<A*> lst;
}
I'm using context property to access object of class B in qml.
How can I access the list in qml. Any sample code will be helpful.

You will need to Q_DECLARE_METATYPE(A *) to be able to wrap it in a QVariant for use in QML.
But that's just for referring to and passing it around QML.
If you want to use A in QML as in C++, it will have to inherit QObject and implement properties, slots and such.
You can see how to implement the QQmlListProperty here: http://doc.qt.io/qt-5/qtqml-referenceexamples-properties-example.html
Also, if QObject is too heavy for you and impractical to have a lot of them, you can always use a single QObject derived to work as a controller for a non-QObject but still registered as metatype type.
class A {
public:
int a;
};
Q_DECLARE_METATYPE(A *)
class AProxy : public QObject {
Q_OBJECT
public slots:
int a(QVariant aVar) {
return aVar.value<A *>()->a;
}
void setA(QVariant aVar, int v) {
aVar.value<A *>()->a = v;
}
};
This way you don't have the size overhead and limitations of QObject for every object in the list, and can instead use a single controller to access the data, albeit at lower performance. In your case you could use B to act as both container and controller proxy for A.

Related

Get object instance class name with Qt's meta-object system

I have 3 classes:
class Being : public QObject {
Q_OBJECT
public:
explicit Being(QObject *parent = nullptr);
};
class Animal : public Being {
Q_OBJECT
public:
explicit Animal(QObject *parent = nullptr);
};
class Dog : public Animal {
Q_OBJECT
public:
explicit Dog(QObject *parent = nullptr);
};
Being's implementation is the following:
Being::Being(QObject *parent) : QObject(parent) {
qDebug() << staticMetaObject.className();
}
I have the following code:
Being *pBeing = new Being();
Being *pAnimal = new Animal();
Being *pDog = new Dog();
Question is: is there a way to implement Being's constructor so that I can have access to the actual instance that points to my Being base class so that the log of the above code will be:
Being
Animal
Dog
?
EDIT:
My intention is that I want to be able to have a Animal.txt, Being.txt and Doc.txt that will be processed inside the Being base class. And I need to know, based on the instance's type, whether I need to parse Animal.txt, Being.txt or Doc.txt to get more information.
Does Qt support this? Is there a mechanism I can use to achieve this using C++/Qt? If not, could there be any elegant compromise solution for this?
It is not possible in the constructor of Being because the enclosing object is not constructed yet, therefore metadata about it is not available. However, you can write the initialize method that should be called after the object construction, e.g. with print function:
class Being : public QObject {
Q_OBJECT
public:
explicit Being(QObject *parent = nullptr) { qDebug() << this->metaObject()->className(); } // this will always print "Being"
void initialize() { qDebug() << this->metaObject()->className(); } // this will print the actual class name
};
class Animal : public Being {
Q_OBJECT
public:
explicit Animal(QObject *parent = nullptr) { initialize(); } // you can already use this method in the constructor
};
TEST(xxx, yyy)
{
Being* being = new Being();
Being* animal = new Animal();
being->initialize();
animal->initialize(); // or you can call it later
}
In case initialize method is not good solution, you can always hack it through Being constructor: explicit Being(QString name, QObject* parent = nullptr; and then explicit Animal(QObject *parent = nullptr): Being("Animal") {}, but I think it is less elegant.
My intention is that I want to be able to have a Animal.txt, Being.txt and Doc.txt that will be processed inside the Being base class. And I need to know, based on the instance's type, whether I need to parse Animal.txt, Being.txt or Doc.txt to get more information.
Never let a base class know anything about its subclasses. Ever.
No matter how tempting it might look like, do no do it (even if you find out how).
A class might have hundreds of subclasses. Take for example QObject. Should QObject (or could it possible) know about your reimplementation of QMainWindow?
So, whatever the reason for this design decision is, change it!
Possible solutions
If the process algorithm of the text files is the same, regardless of the subclass, create a base class method to do the processing and call it from the subclasses.
If the algorithm depends on the subclass, make the method abstract, i.e. virtual and withouth implementation (=0), and let the implementation to the subclasses.

C++ Qt program design issue

In C++ Qt there is a class QWidget
class A inherits QWidget and adds some features
class B inherits A and adds some features
class C inherits B and adds some features, C must be of type QWidget and should do all things done by B
For some reason C is not behaving as expected, I have to rewrite class C. I can not modify code up to class B creation.
How can I solve this problem? Any design pattern, or anything else?
If I try to inherit QWidget and B, a multiple inheritance, there will be two QWidget which leads to problem (QObject - moc does not allow it).
If I inherit from QWidget and pass object of B to C's constructor, whatever operation B performs applies to another QWidget coming through B, which is not desired, all features provided by B should apply to my C's QWidget.
Suppose there is a temperature sensor, when that gets disconnected from machine, class B draws a content blocker image on the whole area of QWidget that it owns, I can monitor sensor connect /disconnect and suppose C's fun. OnDisconnect() gets called, I will call B::OnDisconnect(), B will draw blocker image on its own QWidget, not on the one which is owned by C.
This has everything to do with C++'s rather inflexible method implementation inheritance when compared e.g. to the Common LISP Object System.
Since B's obscuration is always meant to be on top of B's contents, what you effectively need is for B to provide an overlay that draws on top of its contents, even if paintEvent is overriden in derived classes.
See this answer for a simple example, or another answer for an overlay with blur graphical effect.
This is fairly easy to accomplish by having B add an optional overlay widget to itself.
Example:
class OverlayWidget; // from https://stackoverflow.com/a/19367454/1329652
class ObscureOverlay : public OverlayWidget
{
public:
ObscureOverlay(QWidget * parent = {}) : OverlayWidget{parent} {}
protected:
void paintEvent(QPaintEvent *) override {
QPainter p{this};
p.fillRect(rect(), {Qt::black});
}
};
class A : public QWidget {
...
protected:
void paintEvent(QPaintEvent *) override { ... }
};
class B : public A {
...
ObscureOverlay m_obscure{this};
public:
B() {
m_obscure.hide();
}
Q_SLOT void OnDisconnect() {
m_obscure.show();
...
}
};
class C : public B {
...
protected:
void paintEvent(QPaintEvent * event) override {
B::paintEvent(event);
...
}
};
If you don't have the source code to B, you can add the overlay to C, replicating original B's functionality when obscured. All of Qt's slots are effectively virtual, so if you pass a C to someone expecting B and connecting to its OnDisconnect slot, it will be C's slot that will get invoked.
class C : public B {
Q_OBJECT
...
ObscureOverlay m_obscure{this};
public:
explicit C(QWidget * parent = {}) : B{parent} {
m_obscure.hide();
}
Q_SLOT void OnDisconnect() { // slots are effectively virtual
m_obscure.show();
B::OnDisconnect();
}
protected:
void paintEvent(QPaintEvent * event) override {
B::paintEvent(event);
QPainter p{this};
...
}
};

Alternatives to virtual index implementation in a model

So I have again encountered the limits of QObjects that cannot be mixed with templates (at least not directly). Basically I have a proxy model class that uses indexing to translate the source positions to local positions and back. The index can be implemented in number of ways, for now I need two versions, one using QHash and one using QVector. The interface of the index is common to both with only subtle differences regarding index manipulation. With templates this would be easy, I would make the class a template and then used specialization for these two cases.
However the model needs to be a QObject so instead it seems I would need to use polymorphism like so:
class IndexInterface;
class VectorIndex; //inherits IndexInterface
class HashIndex; //inherits IndexInterface
class ProxyModel : public QObject
{
Q_OBJECT
public:
enum IndexType { Vector, Hash };
explicit ProxyModel(IndexType indexType, QObject *parent = 0) :
QObject(parent),
index(indexType == Vector ? new VectorIndex : new HashIndex)
{
}
//...
private:
IndexInterface *index = nullptr;
};
I have couple of issues with this. First, it requires dynamic allocation of the index which I would like to get rid off. Second, because of the use of pointer to IndexInterace to dispatch the calls to the index no method of the index will ever be inlined (I have looked over dissasembled code to confirm this and tried various optimizations etc. to no avail).
What would be the alternatives to this design ideally without dynamic allocation of the index and without virtual calls to the index?
Make the index-type-specific class one of the base classes:
template <typename Index> class IndexHandler {
};
using VectorIndexHandler = IndexHandler<QVector>;
using HashIndexHandler = IndexHandler<QHash>;
class VectorIndexProxy : public QAbstractItemModel, VectorIndexHandler {
... // should be very small
};
class HashIndexProxy : public QAbstractItemModel, HashIndexHandler {
... // should be very small
};
Then instead of passing the index type to the constructor, use a factory function:
QAbstractItemModel * proxyFactory(IndexType indexType, QObject * parent = 0) {
switch (indexType) {
case Foo::Vector:
return new VectorIndexProxy(parent);
...
}
}
If you envision an interface broader or different than QAbstractItemModel, you'll need to write such a base class and derive from it in the concrete implementations, of course.
You could use CRTP if needed for IndexHandler to call directly into the derived class's methods, making it even smaller:
template <typename Index, typename Derived> class IndexHandler {
Derived * derived() { return static_cast<Derived*>(this); }
const Derived * derived() const; // as above
void foo() {
derived()->setObjectName("Yay");
}
};
class VectorIndexProxy :
public QAbstractItemModel,
public VectorIndexHandler<QVector, VectorIndexProxy>
{
... // should be very small
};
You can also "promote" methods from the base class to be Qt slots:
class VectorIndexProxy : ... {
#ifdef Q_MOC_RUN
Q_SLOT void foo();
#endif
};
See this question about having a base non-QObject class with signals and slots.
Finally, you could use the PIMPL idiom, and have a concrete implementation of a fixed type just like you desire. The factory would be invoked in the constructor and you'd be swapping in different PIMPLs for different indices. That's not as expensive as you think since all Qt classes already dynamically allocate a PIMPL, so you can piggy-back on that allocation by deriving your PIMPL from QObjectPrivate (#include <private/qobject_p.h>), and passing the instance of the PIMPL to the protected QObject(QObjectPrivate&). This pattern is omnipresent in Qt, so even though it's an implementation detail, it's not going away in Qt 5 at the very least. Here's a rough sketch:
// ProxyModel.cpp
#include <private/qobject_p.h>
class ProxyModelPrivate : public QObjectPrivate {
// Note: you don't need a q-pointer, QObjectData already provides it
// for you! CAVEAT: q-pointer is not valid until the QObject-derived-class's
// constructor has returned. This would be the case even if you passed
// the q-pointer explicitly, of course.
...
}; // base class
class VectorProxyModelPrivate : public ProxyModelPrivate { ... };
class ProxyModel : public QObject
{
Q_OBJECT
Q_DECLARE_PRIVATE(ProxyModel)
ProxyModel * pimpl(IndexType indexType) {
switch (indexType) {
case Vector: return new VectorProxyModelPrivate();
...
}
public:
enum IndexType { Vector, Hash };
explicit ProxyModel(IndexType indexType, QObject *parent = 0) :
QObject(*pimpl(IndexType), parent)
{}
};
If you were deriving from QAbstractItemModel, your PIMPL would derive from QAbstractItemModelPrivate, in the same fashion; this works for any QObject-deriving class in Qt!

Getting around Qt's templating restrictions

I want to write a simple flexible ftp server in C++ that can be parametrized with a class to handle the user (check login and password, deliver files etc.) supplied on server initialization.
So I came up with this neat (so I thought) idea:
class FtpDelegate
{
public:
FtpDelegate() {}
virtual ~FtpDelegate() {}
virtual bool login(QString username, QString password) = 0;
// ...
};
class DummyDelegate : public FtpDelegate
{
public:
virtual bool login(QString username, QString password)
{
return true;
}
};
template<class Delegate>
class FtpServer : public QObject, Derived_from<Delegate, FtpDelegate>
{
Q_OBJECT
public:
explicit FtpServer(const QHostAddress &address = QHostAddress::Any,
quint16 port = 21,
QObject *parent = 0);
public slots:
void newConnection();
private:
QTcpServer *server;
QHostAddress address;
};
template <class Delegate>
void FtpServer<Delegate>::newConnection()
{
FtpDelegate *delegate = new Delegate();
new FtpConnection (delegate, server->nextPendingConnection(), address, this);
}
class FtpConnection : public QObject
{
Q_OBJECT
public:
explicit FtpConnection(FtpDelegate *delegate,
QTcpSocket *socket,
const QHostAddress &address,
QObject *parent = 0);
public slots:
void newDataConnection();
private:
QTcpSocket *socket;
QTcpServer *dataServer; // needed to transfer data to user
QTcpSocket *dataSocket;
};
// server initialization
FtpServer<DummyDelegate> ftpServer();
and then (you probably saw that coming) bam!
Error: Template classes not supported by Q_OBJECT
it is likely that there are other errors or misconceptions too as I am only starting to learn the C++ template mechanism (and Qt as well).
My question is: what is the best way to make it work without using ugly hacks like passing function pointers or needing to create a factory implementation for each concrete FtpDelegate's derived class. Maybe there's some clever design pattern I just can't see. Eventually I can rewrite the network mechanism to boost if it is the best option.
It is not possible to create a template Q_OBJECT class (see this and answers).
Instead of using static inheritance, you should use a run-time inheritance, and inject an object inheriting from FtpDelegate class.
It looks like the FtpServer is actually a factory creating connections. From your question, I do not see why it has to be Q_OBJECT class. So you may need to reconsider your design, and simplify that class.
what is the best way to make it work without using ugly hacks like passing function pointers or needing to create a factory implementation for each concrete FtpDelegate's derived class.
The best way may be to have a factory class, which creates instances of FtpDelegate type. But you have so many problems in the posted code, that it is not possible to tell more without knowing all gory details.

How to separate hierarchical data and GUI?

I heard that it is better to separate data and GUI. For examples, I have some data. It is hierarchical with abstract base and derived class for concrete types, like
class Data {};
class ConcreteDataA : public Data {};
class ConcreteDataB : public Data {};
And I also have its hierarchical GUI (for example dialog)
class DataDialog {};
class ConcreteDataADialog : public DataDialog {};
class ConcreteDataBDilaog : public DataDialog {};
And I want create a data dialog object from a data object. If the data object is ConcreteDataA, ConcreteDataADialog is created, if B, B dialog is created. There is an easy way to do it by adding a virtual function in class Data like
virtual DataDialog* CreateDialog()
But if I add this function in the data class. it seems to violate the data/GUI separation principle. The second way is to build a global CreateDialog function, and create dialogs according to the dynamic_cast type of data object. This way is also not good for many maual ifs. Any other way to implement it? Or in practice, the first way is also okay? Thanks a lot!
One of my friends told me to use reflection. I think this should work.
It seems that you're looking for an Abstract Factory.
An Abstract Factory is a design pattern in which different types of objects can be created depending on the argument. So in this example, the factory will create a ConcreteDataADialog or a ConcreteDataBDilaog depending on the type of the data.
Code sketch:
class DialogFactory {
public:
virtual Dialog* createDialog() = 0;
};
class ADialogFactory : public DialogFactory {
public:
Dialog* createDialog() {
return new ADialog();
}
};
class BDialogFactory : public DialogFactory {
public:
Dialog* createDialog() {
return new BDialog();
}
};
class Application {
Dialog* createSpecificDialog(Data data) {
if (data.isA()) {
return new ADialogFactory().createDialog();
} else {
return new BDialogFactory().createDialog();
}
}