views:

339

answers:

5

Hi, quick question. Is there any way to (easily) retrieve the parent layout of a widget in Qt?

PS: QObject::parent() won't work, for logical reasons.

EDIT: I'm positive the widget has a parent layout, because I added it to a layout earlier in the code. Now, I have many other layouts in the window and while it is possible for me to keep track of them, I just want to know if there is an easy and clean way to get the parent layout.

EDIT2: Sorry, "easy and clean" was probably not the best way of putting. I meant using the Qt API.

EDIT3: I'm adding the widget to the layout like this:

QHBoxLayout* layout = new QHBoxLayout;

layout->addWidget(button);

+1  A: 

use widget.parent().layout() and search brute force (recursion included) is my only advice. Maybe you can search be "name".

Ronny
I've already tried QObject::parent() and it doesn't work. It returns the parent window.
Austin
this means there is no parent layout.
Ronny
If it is a widget you might want to use widget.layout() if that is what you want
Ronny
to me looks like you have to search with brute force beginning at this parent widgets layout. I'll dig some further.
Ronny
+3  A: 

(Updated answer)

I guess it is not easily possible then. Since a Widget can be technically contained in multiple layouts (a horizontal layout which is aligned inside a vertical layout, for instance).

Just remember that a QWidget's parent does not change if it is aligned in a layout.

You possibly have to keep track of that yourself, then.

BastiBense
That returns the layout contained inside your widget (if any), not the layout containing your widget.
Austin
No, that would return the layout manager installed onto the widget...
ChristopheD
This returns the layout installed on the widget, not the parent layout of the widget (that is, the layout in which this widget is sitting).
Lucas
But parent().layout() should do what they want.
McBeth
@McBeth, it doesn't. The widget is still a child of the window, not the layout.
BastiBense
@BastiBense Of course the widget is a child of its parent widget. But that parent widget has a layout (as asserted by the OP), which may have further layouts, but the original widget will be in there somewhere.
McBeth
@BastiBense, in fact, you can find out if you have the right layout by calling indexOf(widget *) on the layout. It is a little tedious, but it will work. I'm not sure easy or clean is the operative word any more. Everything will be generic enough that you could write it once as a separate function, and will just work however.
McBeth
@McBeth, technically you are correct. But since you can't be 100% sure about the layout structure, I suggest using a simpler, and more secure approach instead of brute-force-searching through everything.
BastiBense
A: 

Have you tried this? Don't forget to check for NULL.

QLayout *parent_layout = qobject_cast< QLayout* >( parent() );

If parent_layout equals NULL, then the parent widget is not a layout.

Lucas
I'm positive the widget has a parent layout.
Austin
A: 

Have you tried QWidget::layout() ?

Paul
Somebody else already suggested this, but edited it out. This one won't work--the reason being that it returns the layout installed on the widget, not the layout containing your widget.
Austin
What do you mean by parent layout then? When you put widget inside a layout in Designer, you actually install that layout on the widget, that layout does not become `QObject::parent()` of that widget. You can easily see that if you look at .h file produced by `uic` from .ui file.
Paul
What I meant is, after placing my widget in layout A, is it possible, with Qt's API, to retrieve layout A later in the code?
Austin
How exactly do you "place" your widget into layout? If you call `A->addWidget(widget)`, then `widget->layout()` should return `A`.If you create widget like `widget = new QWidget(A)`, then `qobject_cast<QLayout*>(widget->parent())` should return A.
Paul
I'm doing A->addWidget(widget). I have tried it and it returns a null pointer (0). Also, widget = new QWidget(A) is not possible, since a layout is not a QWidget and the constructor of QWidget takes a pointer to a QWidget.
Austin
A: 

After some exploration, I found a "partial" solution to the problem.

If you are creating the layout and managing a widget with it, it is possible to retrieve this layout later in the code by using Qt's dynamic properties. Now, to use QWidget::setProperty(), the object you are going to store needs to be a registered meta type. A pointer to QHBoxLayout is not a registered meta type, but there are two workarounds. The simplest workaround is to register the object by adding this anywhere in your code:

Q_DECLARE_METATYPE(QHBoxLayout*)

The second workaround is to wrap the object:

struct Layout {
    QHBoxLayout* layout;
};
Q_DECLARE_METATYPE(Layout)

Once the object is a registered meta type, you can save it this way:

QHBoxLayout* layout = new QHBoxLayout;
QWidget* widget = new QWidget;
widget->setProperty("managingLayout", QVariant::fromValue(layout));
layout->addWidget(widget);

Or this way if you used the second workaround:

QHBoxLayout* layout = new QHBoxLayout;
QWidget* widget = new QWidget;
Layout l;
l.layout = layout;
widget->setProperty("managingLayout", QVariant::fromValue(l));
layout->addWidget(widget);

Later when you need to retrieve the layout, you can retrieve it this way:

QHBoxLayout* layout = widget->property("managingLayout").value<QHBoxLayout*>();

Or like this:

Layout l = widget->property("managingLayout").value<Layout>();
QHBoxLayout* layout = l.layout;

This approach is applicable only when you created the layout. If you did not create the layout and set it, then there is not a simple way of retrieving it later. Also you will have to keep track of the layout and update the managingLayout property when necessary.

Austin