QDockWidget tabify/splitDockWidget weird behavior / bug?
11:10 26 Jan 2015

I have an application with MdiChilds which should contain multiple QDockWidgets. I am however having troubles splitting/tabbing up the Widgets so that they produce the desired default layout. I basically want a layout like this:

QDockWidgetTest desired layout

Widget 4 is created last and needs to go next to the tabified widgets 2 & 3. However, inserting it causes itself and another widget to go missing:

QtDockWidgetTest screenshot

Here's the code producing the second screenshot:

In the constructor of the main window (or the mdi childs, doesn't really matter) I do the following:

QDockWidgetTest::QDockWidgetTest(QWidget *parent)
    : QMainWindow(parent)
{
    ui.setupUi(this);
    setCentralWidget(0); // only QDockWidgets
    QWidget* testWidget1 = new TestWidget("1", QColor("red"));
    QWidget* testWidget2 = new TestWidget("2", QColor("green"));
    QWidget* testWidget3 = new TestWidget("3", QColor("blue"));
    QWidget* testWidget4 = new TestWidget("4", QColor("yellow"));
    DockWidgetWrapper* testQWidget1 = new DockWidgetWrapper(testWidget1, "Test Widget 1", "TestWidget1");
    DockWidgetWrapper* testQWidget2 = new DockWidgetWrapper(testWidget2, "Test Widget 2", "TestWidget2");
    DockWidgetWrapper* testQWidget3 = new DockWidgetWrapper(testWidget3, "Test Widget 3", "TestWidget3");
    DockWidgetWrapper* testQWidget4 = new DockWidgetWrapper(testWidget4, "Test Widget 4", "TestWidget4");
    addDockWidget(Qt::LeftDockWidgetArea, testQWidget1);
    splitDockWidget(testQWidget1, testQWidget2, Qt::Vertical);
    tabifyDockWidget(testQWidget2, testQWidget3);
    splitDockWidget(testQWidget3, testQWidget4, Qt::Horizontal);
}

where TestWidget is a simple QWidget-derived class which is just painting itself in the given color, and the caption in the middle:

#include 
#include 
#include 
#include 

class TestWidget: public QWidget
{
private:
    QString m_content;
    QColor m_fillColor;
public:
    TestWidget(QString content, QColor color):
        m_content(content),
        m_fillColor(color)
    {
        m_fillColor.setAlpha(50);
    }
protected:
    void paintEvent(QPaintEvent* e)
    {
        QPainter p(this);
        QFontMetrics fm(p.font());
        QRect g(geometry());
        p.fillRect(g, m_fillColor);
        p.drawText(g.width()/2 - fm.width(m_content), g.height()/2 + fm.height(), m_content);
    }
};

and DockWidgetWrapper is a simple wrapper into QDockWidget for any QWidget:

#include 
#include 

class DockWidgetWrapper: public QDockWidget
{
public:
    DockWidgetWrapper(QWidget* widget, QString const & windowTitle, QString const & objectName)
    {
        setWindowTitle(windowTitle);
        setFeatures(DockWidgetClosable | DockWidgetMovable | DockWidgetFloatable);
        setWidget(widget);
        setObjectName(objectName);
    }
};

testWidget3 and testWidget4 are completely gone after the last splitDockWidget call, so calling splitDockWidget on a tabified widget makes both the to-be-inserted and the tabified widget disappear. If I bring up the context menu on a QDockWidget header, and make testWidget2 disappear through it, the app looks even more strange:

QtDockWidgetTest after disabling Widget 2

So there is an empty area where testWidget3 and testWidget4 are supposed to be (Qt seems to be under the impression they are still shown, according to the context menu!). Only when disabling those two as well, then the empty area below testWidget1 disappears.

If I split first and then tabify, it's fine. The problem is that I would like to do the tabbing in a general part of the software, and the splitting afterwards when I load a specialized part of it. So reordering the two is not really an option for me. In the documentation I could only find the following on that:

Note: if first is currently in a tabbed docked area, second will be added as a new tab, not as a neighbor of first. This is because a single tab can contain only one dock widget.

This is definitely not what happens. And in addition, this description leaves something to be desired: In my example, it means that once I have tabbed testWidget2 and testWidget3, there is no way to (programmatically) get widget testWidget4 to be to the right of the two, or is there another way to achieve that?

For me this problem consistently occurs with Qt 4.8 and 5.3. I suppose this might be a bug in Qt? Is it a known bug (my search so far has turned up empty)? Or is there any other reasonable explanation for this or a way to "get back" the two lost widgets?

c++ qt qt5 qt4.8