4

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.

Steve Lorimer
  • 27,059
  • 17
  • 118
  • 213

1 Answers1

3

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.

RA.
  • 7,542
  • 1
  • 34
  • 35
  • Thanks, the first suggestion worked perfectly! In fact the only change required was to use `geometry` and `setGeometry` instead of `saveGeometry` / `restoreGeometry` – Steve Lorimer May 17 '17 at 16:52
  • I have the same problem under ubuntu 20.04 and python 3.6. The workaround in this answer didn't worked for me, but if I add a dummy dock widget with the sizes I like to have, and remove if by a singleshot QTimer action, the size of the dock widgets don't changed again. Additionally, there exists a method resizeDocks, but a far as I understand this method, it is used to set the relative size of docks in the same area, not the size of docks in different areas – nhok Jan 22 '21 at 13:17