How to check if a QObject is a descendant of a QObject? - qt

QObject* a;
QObject* b;
//a and b are created somewhere else
bool existed = b.contains(a);//check if b contains a recursively
I'm wondering if there exists any API for this?

You can use QObject::findChildren without any arguments for this purpose:
Something like this:
bool exists = b->findChildren<QObject*>().contains(a);
Note that I think that the fact you need this might imply a design fault and you should rethink what you're trying to accomplish in such a way that this hack isn't necessary. It may well be this cannot be done, but don't just keep doing this kind of thing, as it's quite ugly and can become painfully slow if you're relying on this from the start.

Rather than asking "is 'a' a descendant of 'b'?" try turning it round and asking "is 'b' an ancestor of 'a'?". Then just use repeated calls to QObject::parent. Something like (untested)...
bool is_ancestor_of (const QObject *descendant, const QObject *ancestor)
{
if (!ancestor)
return false;
while (descendant) {
if (descendant == ancestor)
return true;
descendant = descendant->parent();
}
return false;
}

Related

Disambiguation with QMetaObject::invokeMethod and multiple candidates

I wonder if it is possible to call a method with QMetaObject::invokeMethod, if the method has optional parameters like this.
class Foo {
Q_INVOKABLE void myMethod(int a, bool b = true);
}
I have tried :
QMetaObject::invokeMethod(foo, "myMethod", Q_ARG(int, 42), Q_ARG(bool, true));
But the output tells me there are (of course) multiple candidates:
Candidates are:
myMethod(int,bool)
myMethod(int)
Is it possible to disambiguate invokeMethod so I am sure to call myMethod(int,bool) ?
EDIT: I found out that it was an issue with the namespaces for custom classes, instead of ìntandbool`. I wrote a quick and dirty solution.
class Foo {
Q_INVOKABLE void myMethod(bar::A a, blop::B b = blop::B::Default);
}
// When I need to call invokeMethod
auto success = QMetaObject::invokeMethod(foo, "myMethod", Q_ARG(A, A()),
Q_ARG(B, B()));
if(!success) {
QMetaObject::invokeMethod(foo, "myMethod", Q_ARG(bar::A, bar::A()),
Q_ARG(blop::B, blop::B()));
}
But this seems very very very dirty. Anyone got a good solution to handle this ussue?
There's no "good solution" yet. Always fully qualify the arguments to the signals/slots and to the matching string-based connect() and invokeMethod(). The long story is that the lookup is done by string comparison, so you need a perfect match.

QAbstractItemModel foreach iterator with functors: is there a better way to do this?

I'm editing the QDomModel simple example to add some meat for my application, and need to clear some state flags that I've added occasionally. Iterating through the items of a QAbstractItem model is sort of annoying since no standard iterator is provided, so I've written my own for_each-style function to iterate through each item and perform function 'f' on it.
template<typename Functor>
void foreach_item(Functor f, QModelIndex &parent = QModelIndex())
{
if (!parent.isValid())
parent = index(0,0,QModelIndex());
int numRows = rowCount(parent);
for (int i=0; i<numRows; i++)
{
foreach_item(f,index(i,0,parent));
}
f(parent);
}
This works and I can give it all kinds of great lambdas or functors and call it like so:
void QDomModel::clearChanges()
{
foreach_item([&](QModelIndex parent)
{
QDomItem* item = static_cast<QDomItem*>(parent.internalPointer());
item->valueChanged = false;
});
changeCount = 0;
}
This is very powerful, but the problem I'm having is that unless you dug into the code, you'd have no idea what the signature of the functor/lambda is supposed to be. You do get a compile error if you give it something wrong, but I'm worried that this may be a bad interface (or a bad coding practice in general) for creating these types of functions.
Is it better, when taking in arguments, to ask for function pointers for clarity? Are there any implications or limitations to doing one way versus the other that I should be aware of?
std::function will allow you to expose the type in the signature. Try something like:
void foreach_item(const std::function<void(const QModelIndex&)> &f, QModelIndex parent = QModelIndex())
{
/*...*/
}

Synchronizing arbitrary properties in an object transparently in D

Let's say I have a class like so:
class Gerbil{
int id;
float x,y,z;
}
Let's further say this is part of a real-time simulation where I have a server/client setup and I change a property on the server-side:
//...
gerbil.x = 9.0;
//...
Now I want to send over this change to the client to synchronize the world state. However, the problem is I have potentially vast amounts of gerbils, and these gerbils also potentially have long lists of properties—not just x,y,z as depicted here.
My question is: Is there a way we can intercept these property assignments, transparently, and compile a diff from them?
From reading the D reference I got the impression opAssign might be the right thing, only there's actually no examples of how to use it? (D Ref. / opAssign) I suppose it would look something like this, but I'm just shooting from the hip:
void opAssign(string name)(float val){ //Just guessing here
if(name in floatProps){
if(isServer){
changedProps.push(this.id, name, val);
}
floatProps[name] = val;
}
}
And then opAssign would be called when we do:
gerbil.x = 9.0; //Same as gerbil.opAssign!("x")(9.0) ??
Apart from possibly wrong syntax, is this a step in the right direction? What is the right syntax? What about performance? It looks like it could be quite slow? Is there a faster, more "direct" way of this?
What I'd really like to avoid here are elaborate setups like:
gerbil.incProp(Prop.X, 9.0);
Thanks for your time.
Building on Jonathan's answer, I use code like this in a number of my libraries:
public template property(string name, T) {
mixin(`protected T _`~name~`;` ~
propertyGetter!(name, T) ~ propertySetter!(name, T));
}
public template property(string name, T, T def)
{
mixin(`protected T _`~name~` = `~def.stringof~`;` ~
propertyGetter!(name, T) ~ propertySetter!(name, T));
}
template propertyGetter(string name, T) {
enum propertyGetter = `public T `~name~`(){ return _`~name~`; }`;
}
template propertySetter(string name, T) {
enum propertySetter = `public typeof(this) `~name~`(T value){ _`~name~` = value;`~
`/* notify somebody that I've changed here */`~
`return this; }`;
}
The mixin strings are a bit ugly, but they preserve the proper line count.
I add properties to my classes like this:
class Gerbil {
mixin property!("id", int);
mixin property!("x", float);
mixin property!("y", float, 11.0); // give this one a default value
}
If you wanted, you could add some code to the propertySetter template that notified some sort of monitor that it had changed (passing id, property name, and new value). Then the monitor could transmit this info to a corresponding monitor on the server side who would find the object with proper id and set the specified property to the new value.
Overloading opAssign() is like overloading the assignment operator in C++. It's for assigning to the object itself, not one of its members. It's really not going to do what you want. I believe that the closest that you're going to get is properties:
class Gerbil
{
public:
#property int id()
{
return _id;
}
#property id(int newID)
{
//... Do whatever interception you want.
_id = newID;
}
#property float x()
{
return _x;
}
#property x(float newX)
{
//... Do whatever interception you want.
_x = newX;
}
#property float y()
{
return _y;
}
#property y(float newY)
{
//... Do whatever interception you want.
_y = newY;
}
#property float z()
{
return _z;
}
#property z(float newZ)
{
//... Do whatever interception zou want.
_z = newZ;
}
private:
int _id;
float _x, _y, _z;
}
#property enables property syntax so that you can use the function as if it were a variable. So,
//...
auto copyOfGerbilX = gerbil.x; //translates to gerbil.x()
gerbil.x = 9.0; //translates to gerbile.x(9.0)
//...
is now legal even though x is a function rather than a variable. You can insert whatever special handling code you want in the functions. And because the syntax used to access the variables is just as if they were public member variables, you can freely refactor your code to switch between having them be properties or public member variables in your class definition (assuming that you haven't tried to do something like take their address, since that doesn't mean the same thing for a variable as a function).
However, if what you're looking for is a generic way to not have to do all of those functions yourself, there is no direct construct for it. I believe that you could do it with compile-time reflection and string mixins or template mixins which would look at the list of your variables and then generate each of the property functions for you. However, then the extra handling code would have to be essentially the same for each function, and you'd have to be careful that the generated code was really what you wanted. I'm sure that it's feasible, but I'd have to work on the problem for a bit to produce a workable solution.
To generate such code, you'd need to look at __traits and std.traits for the compile-time reflection and at template mixins and string mixins for the code generation. I'd think twice about generating the code like that though rather than writing it by hand. It should be quite doable, but it won't necessarily be easy, debugging it could be entertaining, and if you're going to have to be fairly good with D templates and mixins to get it right.
But essentially, what you're looking for is to use #property functions so that you can add your handler code and then possibly use compile-time reflection along with mixins to generate the code for you, but generating code like that is a fairly advanced technique, so you may want to wait to try that until you're more experienced with D.

How can I find a Qt metaobject instance from a class name?

Is there a way to find the QMetaObject instance of a class, given the class name? what I like to do is to load objects from disk, but for this to happen, I need a way to retrieve a QMetaObject instance using the name of a class, in order to use the QMetaObject to create an instance.
You should be able to do this with QMetaType. You might need Q_DECLARE_META_TYPE() and/or qRegisterMetaType() to make your types known. Then it should work roughly like in this example from the link:
int id = QMetaType::type("MyClass");
if (id == 0) {
void *myClassPtr = QMetaType::construct(id);
...
QMetaType::destroy(id, myClassPtr);
myClassPtr = 0;
}
I have been facing the same problem recently. I needed the metaobject without having to create an instance of the class itself. Best I could do is to create a global / static function that retrieves the qmetaobject given the class name. I achieved this by using QObject::staticMetaObject.
QMetaObject GetMetaObjectByClassName(QString strClassName)
{
QMetaObject metaObj;
if (strClassName.compare("MyClass1") == 0)
{
metaObj = MyClass1::staticMetaObject;
}
else if (strClassName.compare("MyClass2") == 0)
{
metaObj = MyClass2::staticMetaObject;
}
else if (strClassName.compare("MyClass3") == 0)
{
metaObj = MyClass3::staticMetaObject;
}
else if (strClassName.compare("MyClass4") == 0)
{
metaObj = MyClass4::staticMetaObject;
}
else if (strClassName.compare("MyClass5") == 0)
{
metaObj = MyClass5::staticMetaObject;
}
// and so on, you get the idea ...
return metaObj;
}
See : http://doc.qt.io/qt-5/qobject.html#staticMetaObject-var
If somebody has a better option, please share !
You can store the MetaClass instances you will need in a Hash or Map, and then retrieve them via whatever name you stored them under
For your case the appropriate solution can be using Qt plugin mechanism. It offers functionality to easily load shared/dynamic library and check if it contains implementation of some desired interface, if so - create the instance. Details can be found here: How to Create Qt Plugins
You can also take a look at the function: QMetaType::metaObjectForType which
returns QMetaType::metaObject for type
Update: That's my code, it create a class by class name. (Note that the class must be registered with qRegisterMetaType (or is QObject base)
int typeId = QMetaType::type("MyClassName");
const QMetaObject *metaObject = QMetaType::metaObjectForType(typeId);
QObject *o = metaObject->newInstance();
MyClassName *myObj = qobject_cast<MyClassName*>(o);
Update 2: I have forgot to say. Yout class's constructor must be marked as Q_INVOKABLE

Using QSortFilterProxyModel with a tree model

I have a QDirModel whose current directory is set. Then I have a QListView which is supposed to show the files in that directory. This works fine.
Now I want to limit the files shown, so it only shows png files (the filename ends with .png). The problem is that using a QSortFilterProxyModel and setting the filter regexp will try to match every parent of the files as well. According to the documentation:
For hierarchical models, the filter is
applied recursively to all children.
If a parent item doesn't match the
filter, none of its children will be
shown.
So, how do I get the QSortFilterProxyModel to only filter the files in the directory, and not the directories it resides in?
As of Qt 5.10, QSortFilterProxyModel has the option to filter recursively. In other words, if a child matches the filter, its parents will be visible as well.
Check out QSortFilterProxyModel::recursiveFilteringEnabled.
For people like me who are interested in the following behaviour : if a child matches the filter, then its ancestors should not be hidden :
bool MySortFilterProxyModel::filterAcceptsRow(int source_row, const QModelIndex & source_parent) const
{
// custom behaviour :
if(filterRegExp().isEmpty()==false)
{
// get source-model index for current row
QModelIndex source_index = sourceModel()->index(source_row, this->filterKeyColumn(), source_parent) ;
if(source_index.isValid())
{
// if any of children matches the filter, then current index matches the filter as well
int i, nb = sourceModel()->rowCount(source_index) ;
for(i=0; i<nb; ++i)
{
if(filterAcceptsRow(i, source_index))
{
return true ;
}
}
// check current index itself :
QString key = sourceModel()->data(source_index, filterRole()).toString();
return key.contains(filterRegExp()) ;
}
}
// parent call for initial behaviour
return QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent) ;
}
We ran into something similar where I work, and ended up making our own proxy model to do our filtering. However, looking through the documentation for what you want (which seems like it would be a more common case), I came across two possibilities.
You might be able to set a name filter on the QDirModel and filter things that way. I have no idea if this will work like you want, or if the name filters apply to directories also. The documentation is kind of sparse on these.
Subclass the QSortFilterProxyModel and override the filterAcceptsRow function. From the documentation:
Custom filtering behavior can be achieved by reimplementing the filterAcceptsRow() and filterAcceptsColumn() functions.
Then you could presumably use the model index to check if the index item is a directory (automatically accept) or a file (filter on filename).
derive qsortfilterproxymodel and then...
bool YourQSortFilterProxyModel::filterAcceptsRow ( int source_row, const QModelIndex & source_parent ) const
{
if (source_parent == qobject_cast<QStandardItemModel*>(sourceModel())->invisibleRootItem()->index())
{
// always accept children of rootitem, since we want to filter their children
return true;
}
return QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent);
}

Resources