QML/QT How to convert object from C++ to QML? - c++

It took me a while, but eventually I managed to convert a JavaScript/QML POJO to a custom object not derived from QObject.
I think it's easier to understand my issue with a working example. So let's start with this:
struct SomeType { /* Just a plain struct that does not derive from QObject! */ };
SomeType FooFactory::convertQMLToSomeType(const QJSValue& val) {
SomeType result = /*... some kind of conversion takes place here ... */
return result;
}
void FooFactory::registerTypes(QQmlEngine& engine) {
QMetaType::registerConverter<QJSValue, SomeType>(FooFactory::convertQMLToSomeType);
}
What this does is it registers a converter for the transformation of QSValue to SomeType. So now, whenever I do something like this in QML
my_prop = { "foo": "some plain javascript object" };
assuming my_prop is exposed like so in the corresponding C++ class:
Q_PROPERTY(SomeType my_prop MEMBER _myProp);
SomeType _myProp;
// Somewhere else outside the class, this is needed for registering the converter
Q_DECLARE_METATYPE(SomeType);
the string is implicitly converted into a SomeType without the need of doing things manually.
..
Great!
But what about the opposite direction of the conversion? I Need QML to deal with strings, not QVariant(SomeType) objects (QT always uses QVariant wrappers internally to store user defined types when dealing with the meta system).
I already tried registering an inverse converter like this:
QMetaType::registerConverter<SomeType, QJSValue>(FooFactory::convertBackToQML);
or this
QMetaType::registerConverter<QVariant(SomeType), QJSValue>(FooFactory::convertBackToQML);
but none of these approaches work. I believe the second line is quite promising, but I wasn't even able to compile that one due to problems with registering the static meta type.
So, how would I solve this? As a short reminder, I am not able to derive SomeType from QObject, and yes, I am aware that this is the most common way to do these kinds of things.
Does anyone have an idea? Or am I barking up the wrong tree? Many thanks in advance!

This may not be what you want, but it might also be your only option. You can create a QObject wrapper class around your struct. Just create properties for whatever values in the struct you want to expose.
class SomeWrapper : public QObject
{
Q_OBJECT
Q_PROPERTY(QString someData READ someData WRITE setSomeData NOTIFY someDataChanged)
public:
explicit SomeWrapper(QObject *parent = nullptr) : QObject(parent) {}
QString someData() { return m_struct.someData; }
void setSomeData(QString data)
{
if (data != m_struct.someData)
{
m_struct.someData = data;
emit someDataChanged();
}
}
signals:
void someDataChanged();
private:
SomeType m_struct;
};

If you want to operate with your structure as with a plain JavaScript object, then another option may be using QVariantMap as a type for your property. Then you could define the needed conversions in getter and setter of your property:
class Whichever : public QObject {
Q_OBJECT
Q_PROPERTY(QVariantMap my_prop READ myProp WRITE setMyProp)
QVariantMap myProp() const {
QVariantMap map;
map["some_field"] = _myProp.someField;
// Fill the other fields as needed.
return map;
}
void setMyProp(const QVariantMap& map) {
_myProp.someField = map["some_field"].toString();
// Fill the other _myProp fields as needed.
}
};
Conversions between QVariantMap and the actual JavaScript objects would be handled by QML engine automatically. Nested JavaScript objects should also be possible by nesting the corresponding QVariantMaps.
Of course, this option makes property declaration not so explicit about which type does it correspond to, and perhaps it will require a bit more boilerplate code if you need to declare multiple properties of this type (you can define and use your own macro for that though if needed). But this is probably one of the easiest ways to achieve what you have described.

Related

Qt and C++: Overwrite or Expand Class

I want to add some properties (like an ID) to a QPushButton. Therefore, I need to expand or overwrite the class Q_WIDGETS_EXPORT QPushButton : public QAbstractButton
How do I do that?
Thanks for the help.
you dont need to extend the class to just put an id in it ... instead make use of the property system.
as specified in the official doc here:
A property can be read and written using the generic functions QObject::property() and QObject::setProperty(), without knowing anything about the owning class except the property's name.
you just have to do:
ui->myButton->setProperty("Id", 123456);
can also be another object e.g a string (or even your own class if you define it to do that)
ui->myButton->setProperty("_name", "123456");
to read the property is the method property() there for you but read the doc because you get a QVariant as return example:
QVariant(int, 123456)
It really depends on the use case. There is no problem (and often the intended way) in inheriting from Qt-(Widget) Classes (correct me, if I am wrong).
So you could do:
class MyQPushButton : public QPushButton
{
Q_OBJECT
public:
MyQPushButton() : QPushButton(...) {}
private:
int ID = -1;
}
Qt has a very good documentation and you can look at the sources to see what to override.
You could also extend a new class with QPushButton, but than you always have to deal with the QPushButton reference in your class, if you want e.g. connect something. In the inherited class you can connect the slots and so on. But for example you could do this:
class MyQPushButton
{
public:
MyQPushButton() {}
const QPushButton& const GetQPushButton() { return pushButton; }
const QPushButton* const GetQPushButtonPtr() { return &pushButton; }
private:
QPushButton pushButton;
int ID = -1;
}
There is no right and wrong. But I would use the inheritance for Qt-classes.

Function pointer to a non-static member function when the class type is unknown?

I'm working on a game project that features scratch-built controls rendered into an opengl context; things like buttons, scrollbars, listboxes, etc. Many of these controls are nested; for example, my listbox has a scrollbar, a scrollbar has 3 buttons, etc.
When a scrollbar changes value, I'd like it to call 'some' function (typically in it's parent object) that responds to the change. For example, if the listbox has a slider, it should instantiate the slider, then tell the new slider that it should call the listboxes 'onScroll(float)' function. All of the controls share a common base class, so I could have a 'base* parent' parent pointer, then do 'parent->onScroll(val)'. The problem though is what happens when the parent doesn't inheirit from base; there'd be no virtual onScroll() to follow through, so the top-level parent would have to periodically check to see if any of the child controls had changed value. This would also clutter up other controls, since they may not even have children, or may require different event types like when a list entry object is selected, etc.
A better solution would be to have the child object maintain a generic function pointer (like a callback), which can be set by the parent, and called by the child as necessary. Something like this:
typedef (*ptFuncF)(float);
class glBase {
public:
//position,isVisible,virtual mouseDown(x,y),etc
};
class glDerivedChild : public glBase {
public:
glDerivedChild();
~glDerivedChild();
void changeValue(float fIn) {
Value = fIn; //ignore these forward declaration errors
(*callBack)(fIn);
}
void setCallBack(ptFuncF pIn) {callBack = pIn;}
ptFuncF callBack;
float Value;
};
class glDerivedParent : public glBase {
public:
glDerivedParent() {
child = new glDerivedChild();
child->setCallBack(&onScroll);
}
~glDerivedParent() {delete child;}
void onScroll(float fIn) {
//do something
}
glDerivedChild* child;
};
class someFoo {
public:
someFoo() {
child->setCallBack(&setValue);
}
void setValue(float fIn) {
//do something else
}
glDerivedChild child;
};
I'm kinda new to function pointers, so I know I'm (obviously) doing many things wrong. I suspect it might involve something like "typedef (glBase::*ptFuncF)(float);" with the 'onScroll(f)' being an overridden virtual function, perhaps with a generic name like 'virtual void childCallBack(float)'. I'd prefer to keep the solution as close to vanilla as possible, so I want to avoid external libraries like boost. I've been scratching my head over this one for the better part of 8 hours, and I'm hoping someone can help. Thanks!
I think, what you want is some kind of events or signals mechanism.
You can study, how event processing is organized on Windows, for example. In short, your scrollbar generates new event in the system and then system propagates it to all elements, registered in the system.
More convenient mechanism is signal/slot mechanism. Boost or Qt provides such tools. I'll recomend this solution.
But if you still want to use just callbacks, I'll recommend using std::function (boost::function) (combined with std::bind (boost::bind), when required) instead of raw function pointers.
Use boost::function (or std::function if available). Like this (using your notation):
typedef std::function<void (float)> ptFuncF;
//...
void setCallBack(const ptFuncF &pIn);
//...
child->setCallBack(std::bind(&glDerivedParent::onScroll, this, _1));
//...
child->setCallBack(std::bind(&someFoo::setValue, this, _1));
A function pointer to a member function of a class has such a type:
<return type> (<class name>::*)(<arguments>)
For example:
typedef void (glBase::*ptFuncF)(float);
^^^^
by the way, you have forgot the `void` in your `typedef`
ptFuncF func = &glDerivedChild::onScroll;
And you use it like this:
glDerivedChild c;
(c.*func)(1.2);
In your particular example, the function is a member of the derived class itself, therefore you should call it like this:
(c.*c.callback)(1.2);
the inner c.callback is the function pointer. The rest is exactly as above, which is:
(class_instance.*function_pointer)(arguments);
You might want to take a look at this question also.
Ok, the workaround I came up with has some extra overhead and branching, but is otherwise reasonable.
Basically, each callback function is implemented as a virtual member function that recieves the needed parameters including a void* pointer to the object that made the call. Each derived object also has a base-class pointer that refers to the object that should recieve any events that it emits (typically its parent, but could be any object that inheirits from the base class). In case the control has multiple children, the callback function uses the void* pointer to distinguish between them. Here's an example:
class glBase {
public:
virtual onChildCallback(float fIn, void* caller);
glBase* parent;
};
class glSlider : public glBase {
public:
glSlider(glBase* parentIn);
void changeValue(float fIn) {
Value = fIn;
parent->onChildCallback(fIn, this);
}
float Value;
};
class glButton : public glBase {
public:
glButton(glBase* parentIn);
void onClick() {
parent->onChildCallback(0, this);
}
};
class glParent : public glBase {
public:
glParent(glBase* parentIn) : parent(parentIn) {
childA = new glSlider(this);
childB = new glButton(this);
}
void onChildCallback(float fIn, void* caller) {
if (caller == childA) {
//slider specific actions
} else if (caller == childB) {
//button specific actions
} else {
//generic actions
}
}
glSlider* childA;
glButton* childB;
};
Besides a reasonably small amount of overhead, the scheme is flexible enough that derived classes can ignore certain components or omit them altogether. I may go back to the function pointer idea later (thanks shahbaz), but half the infrastructure is the same for both schemes anyway and the extra overhead is minimal, especially since the number and variety of controls will be rather small. Having the callback function use a nested response is actually a little better since you don't need a separate function for each child object (eg onUpButton, onDownButton, etc).

Type-casting to an abstract class?

I'm writing an event-based messaging system to be used between the various singleton managers in my game project. Every manager type (InputManager, AudioManager, etc) is derived from a base Manager class and also inherits from an EventHandler class to facilitate message processing, as follows:
class Manager
{ ... }
class EventHandler
{ ...
virtual void onEvent(Event& e) =0;
...
}
class InputManager : public Manager, public EventHandler
{ ...
virtual void InputManager::onEvent(Event& e);
{ ... }
}
Elsewhere I have an EventManager that keeps track of all EventHandlers and is used for broadcasting events to multiple recievers.
class EventManager
{...
addHandlerToGroup(EventHandler& eh);
{ ... }
...
}
Naturally when I'm initializing all of my singleton Managers, I want to be adding them as they're created to the EventManager's list. My problem is that MVC++ complains at compile-time (and as I'm coding with squiggly lines) whenever I attempt to cast my Managers to EventHandlers. I thought it would work as follows:
int main()
{ ...
EventManager* eventM = new EventManager();
...
InputManager* inputM = new InputManager();
eventM->addHandlerToGroup(dynamic_cast<EventHandler>(inputM));
}
The compiler, however, informs me that "a cast to abstract class is not allowed." I was under the impression that you can...after all, polymorphism doesn't do you much good without passing objects back and forth with a bit of flexibility as to how close to the base class they are interpreted. My current workaround looks like this:
int main()
{ ...
EventManager* eventM = new EventManager();
EventHandler* temp;
...
InputManager* inputM = new InputManager();
temp = inputM;
eventM->addHandlerToGroup(*inputM);
}
Which, as far as I can tell, is the same conceptually for what I'm trying to accomplish, if a bit more verbose and less intuitive. Am I completely off as far as how typecasting with polymorphism works? Where am I going wrong?
in EventManager, declare the method addHandlerToGroup as
void addHandlerToGroup(EventHandler* handler);
then, just remove the cast. pass the pointer (in the example inputM) as it is to the addHandler method, and you should be fine :)
InputManager* inputM = new InputManager();
eventM->addHandlerToGroup(dynamic_cast<EventHandler>(inputM));
I think you just lost track of what you were doing. In this code, inputM is an InputManager* and you are trying to cast it to an EventHandler. That is, you are trying to cast a pointer to one class to an instance of another class. That, of course, makes no sense.
You can cast a pointer to an instance of a derived class to a pointer to an instance of one of its base classes. I think that's what you meant to do.

QHash of function pointers for variable setting after XML parsing: insane?

I am parsing and storing data I get from a server in XML format. The application is a thin client that asks for server-side data like this very frequently. A few of the variables will be uris that trigger more network calls. The data is in the form:
<object>
<var1>value</var1>
...
<varN>value</varN>
</object>
There are ~50 variables in object. The object is mirrored by a MyObject class which has getters and setters for all the variables (which are of different types, and will be accessed by various other classes).
I've been using QXmlStreamReader which is fine, but I end up with a lot of
if (reader.name() == "var1")
{
...
}
entries, and I'm thinking there must be a better way?
I wrote some quick prototype code where MyObject has a function that takes (name, entry), and indexes by name into a QHash of function pointers, that returns the setter to entry, which it calls passing entry. This feels un-Qt-ish, and like something that will confuse a possible future maintainer:
In the header:
typedef void (Foo::*setValue)(QString& value);
QHash<QString, Foo::setValue> m_settersMap;
.cpp:
MyObject::MyObject(QObject *parent) :
QObject(parent)
{
m_settersMap["var1"] = &MyObject::setVar1;
m_settersMap["var2"] = &MyObject::setVar2;
...
m_settersMap["varN"] = &MyObject::setVarN;
}
void MyObject::set(QString &name, QString &entry)
{
MyObject *foo = this;
MyObject::setValue setter;
setter = m_settersMap.value(key);
(*foo.*setter)(value);
}
void MyObject::setVar1(QString &entry)
{
m_foo1 = entry;
}
...
and from the XML handler:
MyObject foo;
...
if(reader.isStartElement())
{
foo.set(reader.name(), reader.readEntryText());
}
This way there's way less copy-pasta in the XML handler, but there's added overhead of the QHash and the possible confusion of a non-straightforward implementation (and my nagging suspicion this is not The Way To Do It).
So is this legit or insane, and have I missed something blindingly obvious?
I'd recommend you another, "easier" solution which will help you to:
1) Have much less code and make your code readable
2) Do not overwhelm another objects with function calls
So you can use QObject properties to do that. And your code would look like as simple as:
// parsing the XML here via QXmlStreamReader
...
QObject *object = new QObject;
...
object->setProperty(reader.name(), reader.value());
And then you can refer to a variable of you object in the code like this:
QString name = object->property("var1").toString();
You may want to extend QObject to get rid of necessity of calling .toString() or something like that all the time.

Design pattern to refactor switch statement

I have something like the following in the header
class MsgBase
{
public:
unsigned int getMsgType() const { return type_; }
...
private:
enum Types { MSG_DERIVED_1, MSG_DERIVED_2, ... MSG_DERIVED_N };
unsigned int type_;
...
};
class MsgDerived1 : public MsgBase { ... };
class MsgDerived2 : public MsgBase { ... };
...
class MsgDerivedN : public MsgBase { ... };
and is used as
MsgBase msgHeader;
// peeks into the input stream to grab the
// base class that has the derived message type
// non-destructively
inputStream.deserializePeek( msgHeader );
unsigned int msgType = msgHeader.getMsgType();
MsgDerived1 msgDerived1;
MsgDerived2 msgDerived2;
...
MsgDerivedN msgDerivedN;
switch( msgType )
{
case MSG_DERIVED_1:
// fills out msgDerived1 from the inputStream
// destructively
inputStream.deserialize( msgDerived1 );
/* do MsgDerived1 processing */
break;
case MSG_DERIVED_2:
inputStream.deserialize( msgDerived2 );
/* do MsgDerived1 processing */
break;
...
case MSG_DERIVED_N:
inputStream.deserialize( msgDerivedN );
/* do MsgDerived1 processing */
break;
}
This seems like the type of situation which would be fairly common and well suited to refactoring. What would be the best way to apply design patterns (or basic C++ language feature redesign) to refactor this code?
I have read that the Command pattern is commonly used to refactor switch statements but that seems only applicable when choosing between algorithms to do a task. Is this a place where the factory or abstract factory pattern is applicable (I am not very familiar with either)? Double dispatch?
I've tried to leave out as much inconsequential context as possible but if I missed something important just let me know and I'll edit to include it. Also, I could not find anything similar but if this is a duplicate just redirect me to the appropriate SO question.
You could use a Factory Method pattern that creates the correct implementation of the base class (derived class) based on the value you peek from the stream.
The switch isn't all bad. It's one way to implement the factory pattern. It's easily testable, it makes it easy to understand the entire range of available objects, and it's good for coverage testing.
Another technique is to build a mapping between your enum types and factories to make the specific objects from the data stream. This turns the compile-time switch into a run-time lookup. The mapping can be built at run-time, making it possible to add new types without recompiling everything.
// You'll have multiple Factories, all using this signature.
typedef MsgBase *(*Factory)(StreamType &);
// For example:
MsgBase *CreateDerived1(StreamType &inputStream) {
MsgDerived1 *ptr = new MsgDerived1;
inputStream.deserialize(ptr);
return ptr;
}
std::map<Types, Factory> knownTypes;
knownTypes[MSG_DERIVED_1] = CreateDerived1;
// Then, given the type, you can instantiate the correct object:
MsgBase *object = (*knownTypes[type])(inputStream);
...
delete object;
Pull Types and type_ out of MsgBase, they don't belong there.
If you want to get totally fancy, register all of your derived types with the factory along with the token (e.g. 'type') that the factory will use to know what to make. Then, the factory looks up that token on deserialize in its table, and creates the right message.
class DerivedMessage : public Message
{
public:
static Message* Create(Stream&);
bool Serialize(Stream&);
private:
static bool isRegistered;
};
// sure, turn this into a macro, use a singleton, whatever you like
bool DerivedMessage::isRegistered =
g_messageFactory.Register(Hash("DerivedMessage"), DerivedMessage::Create);
etc. The Create static method allocates a new DerivedMessage and deserializes it, the Serialize method writes the token (in this case, Hash("DerivedMessage")) and then serializes itself. One of them should probably test isRegistered so that it doesn't get dead stripped by the linker.
(Notably, this method doesn't require an enum or other "static list of everything that can ever exist". At this time I can't think of another method that doesn't require circular references to some degree.)
It's generally a bad idea for a base class to have knowledge about derived classes, so a redesign is definitely in order. A factory pattern is probably what you want here as you already noted.