4
votes

I have a number of QDockWidgets, all docked in a single QMainWindow.

I have overridden the showEvent, and after passing the event on to the base class I am restoring the dock widget's geometry

void DockWidget::showEvent(QShowEvent* ev) 
{
    QDockWidget::showEvent(ev);

    QByteArray byte_array = settings_.value(id + ".geometry").toByteArray();

    LOG("rest: %s", QString(byte_array.toHex()));

    QDockWidget::restoreGeometry(byte_array);
}

In my QMainWindow::closeEvent I am calling saveSettings for each of my dock widgets

void MainWindow::closeEvent(QCloseEvent* ev) 
{
    QList<DockWidget*> dock_widgets = findChildren<DockWidget*>();

    for (DockWidget* dock_widget : dock_widgets)
        dock_widget->saveSettings();

    QMainWindow::closeEvent(ev);
}

In my dock widget's saveSettings function I write the result of saveGeometry to disk:

void DockWidget::saveSettings()
{
    QByteArray byte_array = QDockWidget::saveGeometry();

    LOG("save: %s", QString(byte_array.toHex()));

    settings_.setValue(id + ".geometry", byte_array);
    settings_.sync();
}

Whilst this does work when my QMainWindow is not maximized, when it is maximized the widgets aren't restored correctly.

In this image I have arranged my widgets just prior to closing. (linked because inline the image will be too large)

In this image I reload my app and the widgets' geometry is incorrectly loaded.

You can see in my functions above I log the geometry string being saved and loaded.

I have proven to myself that the settings are correctly saved and restored again, but somehow it's not working correctly

close the app; save the state:

save: 01d9d0cb000200000000053f000000640000077f000001a00000053f000000640000077f000001a000000000000000000780

open the app; restore the state: (the hex data here matches the saved one exactly)

rest: 01d9d0cb000200000000053f000000640000077f000001a00000053f000000640000077f000001a000000000000000000780

close the app again, having touched nothing: (the hex data is different now, as the geometry is different, see marks below)

save: 01d9d0cb000200000000053f000000640000077f0000014e0000053f000000640000077f0000014e00000000000000000780
                                                    ^                               ^

This doesn't happen when the window is not maximized.

Is this a bug in Qt, or am I not using the functionality correctly?

I am using Qt 5.5 on Ubuntu 16.04.

1

1 Answers

3
votes

This is a bug in Qt. Specifically, QTBUG-46620 and possibly also QTBUG-16252.

The bug report for QTBUG-46620 details a work-around, which you should try. To begin with, ensure that the main window geometry and main window state are saved when you close the application (note that you should not have to save the geometry of each dock window separately):

void MainWindow::closeEvent(QCloseEvent* ev)
{
     settings_.setValue("geometry", saveGeometry());
     settings_.setValue("state", saveState());
}

Then, restore the geometry as follows:

restoreGeometry(settings.value("geometry").toByteArray());
if (isMaximized())
{
    setGeometry( QApplication::desktop()->availableGeometry(this) );
}
restoreState(settings.value("windowState").toByteArray());

If the you have trouble with the above work-around, you may also have to save the maximized state of the window:

void MainWindow::closeEvent(QCloseEvent* ev)
{
     settings_.setValue("geometry", saveGeometry());
     settings_.setValue("state", saveState());
     settings_.setValue("maximized", isMaximized());
}

Then restore as follows:

restoreGeometry(settings.value("geometry").toByteArray());
if (settings.value("maximized").toBool())
{
    showMaximized();
    setGeometry( QApplication::desktop()->availableGeometry(this) );
}
restoreState(settings.value("windowState").toByteArray());

Note that these work-arounds may cause some warning messages to be generated on some platforms.