Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Preserving/Restoring QDockWidget size

Preserving/Restoring QDockWidget size

Scheduled Pinned Locked Moved Unsolved General and Desktop
27 Posts 4 Posters 4.2k Views 3 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • PerdrixP Offline
    PerdrixP Offline
    Perdrix
    wrote on last edited by Perdrix
    #1

    The size of a resizeable QDockWidget that is docked does not appear to be correctly preserved and restored when the application is close and restarted.

    This is my code to save the window state and geometry on application shutdown:

    QSettings settings;
    settings.beginGroup("MainWindow");
    auto geometry{ saveGeometry() };
    settings.setValue("geometry", geometry);
    #ifndef NDEBUG	
    ZTRACE_RUNTIME("Hex dump of geometry:");
    ZTrace::dumpHex(geometry.constData(), geometry.length());
    #endif 
    
    auto windowState{ saveState()};
    settings.setValue("windowState", saveState());
    #ifndef NDEBUG	
    ZTRACE_RUNTIME("Hex dump of windowState:");
    ZTrace::dumpHex(windowState.constData(), windowState.length());
    #endif
    settings.setValue("maximised", isMaximized());
    
    settings.endGroup();
    QTableView* tableView = this->findChild<QTableView*>("tableView");
    settings.setValue("Dialogs/PictureList/TableView/HorizontalHeader/windowState",
    		tableView->horizontalHeader()->saveState());
    settings.sync();
    

    Which produces this in my trace - for example:

    00000059 2023/10/19 15:32:34.516 014612 00005d30     >Saving Window State and Position
    00000060 2023/10/19 15:32:34.516 014612 00005d30     >Hex dump of geometry:
    00000061 2023/10/19 15:32:34.517 014612 00005d30     >0000000002680D80:  01D9D0CB 00030000 000003B2 0000010C  ................
    00000062 2023/10/19 15:32:34.517 014612 00005d30     >0000000002680D90:  00000A93 0000053C 000003B2 0000012A  .......<.......*
    00000063 2023/10/19 15:32:34.517 014612 00005d30     >0000000002680DA0:  00000A93 0000053C 00000000 00000000  .......<........
    00000064 2023/10/19 15:32:34.517 014612 00005d30     >0000000002680DB0:  0C000000 03B20000 012A0000 0A930000  .........*......
    00000065 2023/10/19 15:32:34.517 014612 00005d30     >0000000002680DC0:  053C                                 .<              
    00000066 2023/10/19 15:32:34.518 014612 00005d30     >Hex dump of windowState:
    00000067 2023/10/19 15:32:34.518 014612 00005d30     >00000000068F6400:  000000FF 00000000 FD000000 02000000  ................
    00000068 2023/10/19 15:32:34.518 014612 00005d30     >00000000068F6410:  00000001 22000003 F8FC0200 000001FB  ...."...........
    00000069 2023/10/19 15:32:34.519 014612 00005d30     >00000000068F6420:  00000016 00450078 0070006C 006F0072  .....E.x.p.l.o.r
    00000070 2023/10/19 15:32:34.519 014612 00005d30     >00000000068F6430:  00650072 00420061 00720100 00000000  .e.r.B.a.r......
    00000071 2023/10/19 15:32:34.519 014612 00005d30     >00000000068F6440:  0003F800 0001C600 07FFFF00 00000300  ................
    00000072 2023/10/19 15:32:34.519 014612 00005d30     >00000000068F6450:  0005BA00 000294FC 01000000 01FB0000  ................
    00000073 2023/10/19 15:32:34.519 014612 00005d30     >00000000068F6460:  00160050 00690063 00740075 00720065  ...P.i.c.t.u.r.e
    00000074 2023/10/19 15:32:34.520 014612 00005d30     >00000000068F6470:  004C0069 00730074 01000001 28000005  .L.i.s.t....(...
    00000075 2023/10/19 15:32:34.520 014612 00005d30     >00000000068F6480:  BA000002 7100FFFF FF000005 BA000001  ....q...........
    00000076 2023/10/19 15:32:34.520 014612 00005d30     >00000000068F6490:  5E000000 01000000 04000000 01000000  ^...............
    00000077 2023/10/19 15:32:34.521 014612 00005d30     >00000000068F64A0:  08FC0000 0000                        ......          
    
    

    When I restart the application this code is used:

    //
    // Set initial size of the bottom dock widget (pictureList)
    //
    resizeDocks({ pictureList }, { 150 }, Qt::Vertical);
    
    ZTRACE_RUNTIME("Restoring Window State and Position");
    QSettings settings;
    settings.beginGroup("MainWindow");
    
    auto geometry{ settings.value("geometry", QByteArray()).toByteArray() };
    auto windowState{ settings.value("windowState", QByteArray()).toByteArray() };
    
    #ifndef NDEBUG
    if (geometry.length())
    {
    	ZTRACE_RUNTIME("Hex dump of geometry:");
    	ZTrace::dumpHex(geometry.constData(), geometry.length());
    }
    if (windowState.length())
    {
    	ZTRACE_RUNTIME("Hex dump of windowState:");
    	ZTrace::dumpHex(windowState.constData(), windowState.length());
    }
    #endif
    
    if (settings.value("maximised").toBool())
    {
    	showMaximized();
    	setGeometry(screen()->availableGeometry());
    }
    else restoreGeometry(geometry);
    
    if (windowState.length())
    {
    	restoreState(windowState);
    	restoreDockWidget(pictureList);
    }
    settings.endGroup();
    

    but that doesn't seem to restore the vertical size of the dock widget (pictureList).

    What am I failing to do/doing wrong please?

    1 Reply Last reply
    0
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Hi,

      Did you set an object name on all your QDockWidget objects ?

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      PerdrixP 1 Reply Last reply
      1
      • SGaistS SGaist

        Hi,

        Did you set an object name on all your QDockWidget objects ?

        PerdrixP Offline
        PerdrixP Offline
        Perdrix
        wrote on last edited by Perdrix
        #3

        @SGaist All the dock widgets have the object name set.

        Also is the code to restore the dock widget correct - i.e.:
        if (windowState.length())
        {
        restoreState(windowState);
        restoreDockWidget(pictureList);
        }

        Axel SpoerlA 1 Reply Last reply
        0
        • PerdrixP Perdrix

          @SGaist All the dock widgets have the object name set.

          Also is the code to restore the dock widget correct - i.e.:
          if (windowState.length())
          {
          restoreState(windowState);
          restoreDockWidget(pictureList);
          }

          Axel SpoerlA Online
          Axel SpoerlA Online
          Axel Spoerl
          Moderators
          wrote on last edited by
          #4

          @Perdrix
          Saving the geometry of a dock widget hasn't been implemented.
          You would have to serialize that manually.

          A small nitpick: When reading settings, I'd prefer to instantiate const QSettings settings, just to make sure I don't write anything by accident. Flushing with sync() otherwise happens automagically when the object goes out of scope.

          Software Engineer
          The Qt Company, Oslo

          PerdrixP 1 Reply Last reply
          1
          • Axel SpoerlA Axel Spoerl

            @Perdrix
            Saving the geometry of a dock widget hasn't been implemented.
            You would have to serialize that manually.

            A small nitpick: When reading settings, I'd prefer to instantiate const QSettings settings, just to make sure I don't write anything by accident. Flushing with sync() otherwise happens automagically when the object goes out of scope.

            PerdrixP Offline
            PerdrixP Offline
            Perdrix
            wrote on last edited by Perdrix
            #5

            @Axel-Spoerl Oh! No wonder I was having trouble getting that to work. I thought that's what restoreDockWidget() did given the windowState of the main window!

            If I need to save the geometry of the dock widget (whether docked or not) how should I do that?

            I just checked the documentation again and it clearly says:

            QByteArray QWidget::saveGeometry() const

            Saves the current geometry and state for top-level widgets.
            To save the geometry when the window closes, you can implement a close event like this:
            void MyWidget::closeEvent(QCloseEvent *event)
            {
            QSettings settings("MyCompany", "MyApp");
            settings.setValue("geometry", saveGeometry());
            QWidget::closeEvent(event);
            }

            See the Window Geometry documentation for an overview of geometry issues with windows.
            Use QMainWindow::saveState() to save the geometry and the state of toolbars and dock widgets.

            Axel SpoerlA 1 Reply Last reply
            0
            • PerdrixP Perdrix

              @Axel-Spoerl Oh! No wonder I was having trouble getting that to work. I thought that's what restoreDockWidget() did given the windowState of the main window!

              If I need to save the geometry of the dock widget (whether docked or not) how should I do that?

              I just checked the documentation again and it clearly says:

              QByteArray QWidget::saveGeometry() const

              Saves the current geometry and state for top-level widgets.
              To save the geometry when the window closes, you can implement a close event like this:
              void MyWidget::closeEvent(QCloseEvent *event)
              {
              QSettings settings("MyCompany", "MyApp");
              settings.setValue("geometry", saveGeometry());
              QWidget::closeEvent(event);
              }

              See the Window Geometry documentation for an overview of geometry issues with windows.
              Use QMainWindow::saveState() to save the geometry and the state of toolbars and dock widgets.

              Axel SpoerlA Online
              Axel SpoerlA Online
              Axel Spoerl
              Moderators
              wrote on last edited by
              #6

              @Perdrix
              restoreDockWidget() is a mixed bag IMHO. It basically restores what the main window needs to know about its dock widgets. Their geometry doesn't fall into that category.

              The code snippet you mention is meant to be included in a class inheriting from QWidget. As far as I know your app, you are using generic dock widgets.

              So the question is, is the dock widgets' geometry the right one at the moment, where you call QMainWindow::saveState()? If so, just loop over the dock widgets and do as laid out in the code snippet. If not (because they might have been closed manually at an earlier time), you would have to install an event filter on each dock widget and intercept the event that hides, closes or resizes a dock widget. If you don't wanna write into the settings file from an event, you could store the returned QByteArray in a QHashand use that to restore geometries at run time. When saving settings, you could translate the hashed pointer into an object name, store the hash in the settings and rebuild it on next application startup.

              Software Engineer
              The Qt Company, Oslo

              PerdrixP 1 Reply Last reply
              2
              • Axel SpoerlA Axel Spoerl

                @Perdrix
                restoreDockWidget() is a mixed bag IMHO. It basically restores what the main window needs to know about its dock widgets. Their geometry doesn't fall into that category.

                The code snippet you mention is meant to be included in a class inheriting from QWidget. As far as I know your app, you are using generic dock widgets.

                So the question is, is the dock widgets' geometry the right one at the moment, where you call QMainWindow::saveState()? If so, just loop over the dock widgets and do as laid out in the code snippet. If not (because they might have been closed manually at an earlier time), you would have to install an event filter on each dock widget and intercept the event that hides, closes or resizes a dock widget. If you don't wanna write into the settings file from an event, you could store the returned QByteArray in a QHashand use that to restore geometries at run time. When saving settings, you could translate the hashed pointer into an object name, store the hash in the settings and rebuild it on next application startup.

                PerdrixP Offline
                PerdrixP Offline
                Perdrix
                wrote on last edited by
                #7

                @Axel-Spoerl But that's my complaint - it doesn't restore the size of the docked dock widget to what it was when the application closed.

                So I have to ask again how can this be made to work? I'm prepared to add extra code enquire on the geometry of the dock widget and restore it after open, but only if that has some chance to work.

                PerdrixP 1 Reply Last reply
                0
                • PerdrixP Perdrix

                  @Axel-Spoerl But that's my complaint - it doesn't restore the size of the docked dock widget to what it was when the application closed.

                  So I have to ask again how can this be made to work? I'm prepared to add extra code enquire on the geometry of the dock widget and restore it after open, but only if that has some chance to work.

                  PerdrixP Offline
                  PerdrixP Offline
                  Perdrix
                  wrote on last edited by
                  #8

                  @Axel-Spoerl I tried this:

                  	//
                  	// Now save the geometry of the Picture List dock widget
                  	//
                  	settings.beginGroup("PictureList");
                  	geometry = pictureList->saveGeometry();
                  #ifndef NDEBUG	
                  	ZTRACE_RUNTIME("Hex dump of Picture List geometry:");
                  	ZTrace::dumpHex(geometry.constData(), geometry.length());
                  #endif 
                  	settings.endGroup();
                  
                  	if (windowState.length())
                  	{
                  		restoreState(windowState);
                  		restoreDockWidget(pictureList);
                  
                  		settings.beginGroup("PictureList");
                  		geometry = settings.value("geometry", QByteArray()).toByteArray();
                  		settings.endGroup();
                  
                  		if (geometry.length())
                  		{
                  			pictureList->restoreGeometry(geometry);
                  		}
                  	}
                  
                  

                  But even though I saved the dock widget's geometry explicitly restoring it didn't change the size to match what it was when the application closed.

                  :(
                  David

                  Axel SpoerlA 1 Reply Last reply
                  0
                  • PerdrixP Perdrix

                    @Axel-Spoerl I tried this:

                    	//
                    	// Now save the geometry of the Picture List dock widget
                    	//
                    	settings.beginGroup("PictureList");
                    	geometry = pictureList->saveGeometry();
                    #ifndef NDEBUG	
                    	ZTRACE_RUNTIME("Hex dump of Picture List geometry:");
                    	ZTrace::dumpHex(geometry.constData(), geometry.length());
                    #endif 
                    	settings.endGroup();
                    
                    	if (windowState.length())
                    	{
                    		restoreState(windowState);
                    		restoreDockWidget(pictureList);
                    
                    		settings.beginGroup("PictureList");
                    		geometry = settings.value("geometry", QByteArray()).toByteArray();
                    		settings.endGroup();
                    
                    		if (geometry.length())
                    		{
                    			pictureList->restoreGeometry(geometry);
                    		}
                    	}
                    
                    

                    But even though I saved the dock widget's geometry explicitly restoring it didn't change the size to match what it was when the application closed.

                    :(
                    David

                    Axel SpoerlA Online
                    Axel SpoerlA Online
                    Axel Spoerl
                    Moderators
                    wrote on last edited by
                    #9

                    @Perdrix
                    Hi David,
                    I shall have a look and revert back to you asap.
                    cheers
                    Axel

                    Software Engineer
                    The Qt Company, Oslo

                    PerdrixP 1 Reply Last reply
                    0
                    • Axel SpoerlA Axel Spoerl

                      @Perdrix
                      Hi David,
                      I shall have a look and revert back to you asap.
                      cheers
                      Axel

                      PerdrixP Offline
                      PerdrixP Offline
                      Perdrix
                      wrote on last edited by
                      #10

                      @Axel-Spoerl Thank you Axel.

                      FYI I also tried:

                      	//
                      	// Now save the height of the Picture List dock widget
                      	//
                      	settings.beginGroup("PictureList");
                      	auto height = pictureList->height();
                      	settings.setValue("Height", height);
                      #ifndef NDEBUG	
                      	ZTRACE_RUNTIME("Height of Picture List was %d pixels", height);
                      #endif 
                      	settings.endGroup();
                      

                      and

                      if (windowState.length())
                      	{
                      		restoreState(windowState);
                      		restoreDockWidget(pictureList);
                      
                      		settings.beginGroup("PictureList");
                      		auto height = settings.value("Height", 0).toInt();
                      		settings.endGroup();
                      
                      		if (height)
                      		{
                      			resizeDocks({ pictureList }, { height }, Qt::Vertical);
                      		}
                      	}
                      

                      which also didn't work :(

                      PerdrixP 1 Reply Last reply
                      0
                      • PerdrixP Perdrix

                        @Axel-Spoerl Thank you Axel.

                        FYI I also tried:

                        	//
                        	// Now save the height of the Picture List dock widget
                        	//
                        	settings.beginGroup("PictureList");
                        	auto height = pictureList->height();
                        	settings.setValue("Height", height);
                        #ifndef NDEBUG	
                        	ZTRACE_RUNTIME("Height of Picture List was %d pixels", height);
                        #endif 
                        	settings.endGroup();
                        

                        and

                        if (windowState.length())
                        	{
                        		restoreState(windowState);
                        		restoreDockWidget(pictureList);
                        
                        		settings.beginGroup("PictureList");
                        		auto height = settings.value("Height", 0).toInt();
                        		settings.endGroup();
                        
                        		if (height)
                        		{
                        			resizeDocks({ pictureList }, { height }, Qt::Vertical);
                        		}
                        	}
                        

                        which also didn't work :(

                        PerdrixP Offline
                        PerdrixP Offline
                        Perdrix
                        wrote on last edited by Perdrix
                        #11

                        @Axel-Spoerl Odd

                        This code looks as if it is saving the sizes of the dock widgets ...

                        void QDockAreaLayout::saveState(QDataStream &stream) const
                        {
                            stream << (uchar) DockWidgetStateMarker;
                            int cnt = 0;
                            for (int i = 0; i < QInternal::DockCount; ++i) {
                                if (!docks[i].item_list.isEmpty())
                                    ++cnt;
                            }
                            stream << cnt;
                            for (int i = 0; i < QInternal::DockCount; ++i) {
                                if (docks[i].item_list.isEmpty())
                                    continue;
                                stream << i << docks[i].rect.size();
                                docks[i].saveState(stream);
                            }
                        
                            stream << centralWidgetRect.size();
                        
                            for (int i = 0; i < 4; ++i)
                                stream << static_cast<int>(corners[i]);
                        }
                        
                        Axel SpoerlA 1 Reply Last reply
                        0
                        • PerdrixP Perdrix

                          @Axel-Spoerl Odd

                          This code looks as if it is saving the sizes of the dock widgets ...

                          void QDockAreaLayout::saveState(QDataStream &stream) const
                          {
                              stream << (uchar) DockWidgetStateMarker;
                              int cnt = 0;
                              for (int i = 0; i < QInternal::DockCount; ++i) {
                                  if (!docks[i].item_list.isEmpty())
                                      ++cnt;
                              }
                              stream << cnt;
                              for (int i = 0; i < QInternal::DockCount; ++i) {
                                  if (docks[i].item_list.isEmpty())
                                      continue;
                                  stream << i << docks[i].rect.size();
                                  docks[i].saveState(stream);
                              }
                          
                              stream << centralWidgetRect.size();
                          
                              for (int i = 0; i < 4; ++i)
                                  stream << static_cast<int>(corners[i]);
                          }
                          
                          Axel SpoerlA Online
                          Axel SpoerlA Online
                          Axel Spoerl
                          Moderators
                          wrote on last edited by
                          #12

                          @Perdrix
                          Hi David,
                          making sure we're on the same page.
                          The workflow is:

                          • application starts with a docked dock widget.
                          • dock widget is unplugged programmatically by setFloating(true).
                          • dock widget is resized, either manually or programmatically.
                          • application is closed, state and geometry are saved.
                          • application is started again, state and geometry are restored.
                          • problem: dock widget bounces back to default geometry.

                          Cheers
                          Axel

                          Software Engineer
                          The Qt Company, Oslo

                          Axel SpoerlA 1 Reply Last reply
                          0
                          • Axel SpoerlA Axel Spoerl

                            @Perdrix
                            Hi David,
                            making sure we're on the same page.
                            The workflow is:

                            • application starts with a docked dock widget.
                            • dock widget is unplugged programmatically by setFloating(true).
                            • dock widget is resized, either manually or programmatically.
                            • application is closed, state and geometry are saved.
                            • application is started again, state and geometry are restored.
                            • problem: dock widget bounces back to default geometry.

                            Cheers
                            Axel

                            Axel SpoerlA Online
                            Axel SpoerlA Online
                            Axel Spoerl
                            Moderators
                            wrote on last edited by
                            #13

                            @Axel-Spoerl
                            Ok, I must apologize, you have found a bug, a missing feature, whatever you wanna call it.

                            If I understand you correctly, the issue is the undocked geometry.
                            It is held by QDockWidgetPrivate::undockedGeometryand unfortunately not saved anywhere.
                            I'll look into a fix. It is, however, not an easy patch. QWidget::saveGeometry() is not virtual, so the straight forward approach of overriding it in QDockWidgetwon't fly. The undocked geometry is held in the private header, without public accessors, so a stright forward workaround won't fly either.

                            • The fix will probably be a version bump of QDockAreaLayout::saveState(). But that'll kick be available in the next release of 6.5 at the earliest.
                            • The workaround is a bit of plumbing. When the application closes, all dock widgets need to be made floating, after the main window state was saved. Then their undocked geometry becomes available in geometry()and needs to be saved as well. I'll be back with a suggestion.

                            Software Engineer
                            The Qt Company, Oslo

                            PerdrixP 1 Reply Last reply
                            0
                            • Axel SpoerlA Axel Spoerl

                              @Axel-Spoerl
                              Ok, I must apologize, you have found a bug, a missing feature, whatever you wanna call it.

                              If I understand you correctly, the issue is the undocked geometry.
                              It is held by QDockWidgetPrivate::undockedGeometryand unfortunately not saved anywhere.
                              I'll look into a fix. It is, however, not an easy patch. QWidget::saveGeometry() is not virtual, so the straight forward approach of overriding it in QDockWidgetwon't fly. The undocked geometry is held in the private header, without public accessors, so a stright forward workaround won't fly either.

                              • The fix will probably be a version bump of QDockAreaLayout::saveState(). But that'll kick be available in the next release of 6.5 at the earliest.
                              • The workaround is a bit of plumbing. When the application closes, all dock widgets need to be made floating, after the main window state was saved. Then their undocked geometry becomes available in geometry()and needs to be saved as well. I'll be back with a suggestion.
                              PerdrixP Offline
                              PerdrixP Offline
                              Perdrix
                              wrote on last edited by
                              #14

                              @Axel-Spoerl Nope this is the DOCKED size.

                              So work flow is:

                              • Open application
                                6ee9c494-fce0-4947-a69c-92c56fba517d-image.png
                              • Adjust vertical height of lower dock widget
                                08dc0861-5191-4bf2-b7ec-5994599c8868-image.png
                              • Close application
                              • Reopen application. Size lower dock widget is same as if lower dock widget hadn't been resized.
                                e7553192-017e-4b40-87c9-53f6c62f13fc-image.png
                              Axel SpoerlA 1 Reply Last reply
                              0
                              • PerdrixP Perdrix

                                @Axel-Spoerl Nope this is the DOCKED size.

                                So work flow is:

                                • Open application
                                  6ee9c494-fce0-4947-a69c-92c56fba517d-image.png
                                • Adjust vertical height of lower dock widget
                                  08dc0861-5191-4bf2-b7ec-5994599c8868-image.png
                                • Close application
                                • Reopen application. Size lower dock widget is same as if lower dock widget hadn't been resized.
                                  e7553192-017e-4b40-87c9-53f6c62f13fc-image.png
                                Axel SpoerlA Online
                                Axel SpoerlA Online
                                Axel Spoerl
                                Moderators
                                wrote on last edited by
                                #15

                                @Perdrix
                                Hi David,

                                so we're not talking about undocked dock widgets' geometry?
                                In that case, you're not affected by the bug, that the undocked geometry is not saved.

                                I have the feeling that something is wrong in the application code.

                                Just tried to demonstrate the problem in a simple reproducer. But there is no problem, it works perfectly

                                mainwindow.h

                                #ifndef MAINWINDOW_H
                                #define MAINWINDOW_H
                                
                                #include <QMainWindow>
                                #include <QDockWidget>
                                
                                QT_BEGIN_NAMESPACE
                                namespace Ui { class MainWindow; }
                                QT_END_NAMESPACE
                                
                                class MainWindow : public QMainWindow
                                {
                                    Q_OBJECT
                                
                                public:
                                    MainWindow(QWidget *parent = nullptr);
                                    ~MainWindow();
                                
                                private:
                                    void readSettings();
                                    void writeSettings() const;
                                    Ui::MainWindow *ui;
                                };
                                #endif // MAINWINDOW_H
                                

                                mainwindow.cpp

                                #include "mainwindow.h"
                                #include "./ui_mainwindow.h"
                                #include <QSettings>
                                
                                MainWindow::MainWindow(QWidget *parent)
                                    : QMainWindow(parent)
                                    , ui(new Ui::MainWindow)
                                {
                                    ui->setupUi(this);
                                
                                    for (int i = 0; i < 4; ++i) {
                                        const QString name = "DockWidget-" + QString::number(i);
                                        QDockWidget *dw = new QDockWidget(name, this);
                                        dw->setObjectName(name);
                                        addDockWidget(static_cast<Qt::DockWidgetArea>(i << 2), dw);
                                    }
                                    readSettings();
                                }
                                
                                MainWindow::~MainWindow()
                                {
                                    writeSettings();
                                    delete ui;
                                }
                                
                                void MainWindow::readSettings()
                                {
                                    const QSettings s("Test", "DockWidgetGeometry");
                                    if (!s.contains("MainWindowState"))
                                        return;
                                
                                    const QByteArray array = s.value("MainWindowState").toByteArray();
                                    restoreState(array);
                                }
                                
                                void MainWindow::writeSettings() const
                                {
                                    QSettings s("Test", "DockWidgetGeometry");
                                    s.setValue("MainWindowState", saveState());
                                }
                                

                                main.cpp

                                #include "mainwindow.h"
                                
                                #include <QApplication>
                                
                                int main(int argc, char *argv[])
                                {
                                    QApplication a(argc, argv);
                                    MainWindow w;
                                    w.show();
                                    return a.exec();
                                }
                                

                                I start the application, move all dock widgets to the left dock, join two as floating tabs, change their sizes. Whatever I do is exactly recovered after closing and re-starting the app.

                                22674419-3425-4bb8-adbb-9b35f1c08c49-image.png

                                So I suspect that your application touches the docked dockwidgets' size after the state is restored.

                                Cheers
                                Axel

                                Software Engineer
                                The Qt Company, Oslo

                                PerdrixP 1 Reply Last reply
                                0
                                • Axel SpoerlA Axel Spoerl

                                  @Perdrix
                                  Hi David,

                                  so we're not talking about undocked dock widgets' geometry?
                                  In that case, you're not affected by the bug, that the undocked geometry is not saved.

                                  I have the feeling that something is wrong in the application code.

                                  Just tried to demonstrate the problem in a simple reproducer. But there is no problem, it works perfectly

                                  mainwindow.h

                                  #ifndef MAINWINDOW_H
                                  #define MAINWINDOW_H
                                  
                                  #include <QMainWindow>
                                  #include <QDockWidget>
                                  
                                  QT_BEGIN_NAMESPACE
                                  namespace Ui { class MainWindow; }
                                  QT_END_NAMESPACE
                                  
                                  class MainWindow : public QMainWindow
                                  {
                                      Q_OBJECT
                                  
                                  public:
                                      MainWindow(QWidget *parent = nullptr);
                                      ~MainWindow();
                                  
                                  private:
                                      void readSettings();
                                      void writeSettings() const;
                                      Ui::MainWindow *ui;
                                  };
                                  #endif // MAINWINDOW_H
                                  

                                  mainwindow.cpp

                                  #include "mainwindow.h"
                                  #include "./ui_mainwindow.h"
                                  #include <QSettings>
                                  
                                  MainWindow::MainWindow(QWidget *parent)
                                      : QMainWindow(parent)
                                      , ui(new Ui::MainWindow)
                                  {
                                      ui->setupUi(this);
                                  
                                      for (int i = 0; i < 4; ++i) {
                                          const QString name = "DockWidget-" + QString::number(i);
                                          QDockWidget *dw = new QDockWidget(name, this);
                                          dw->setObjectName(name);
                                          addDockWidget(static_cast<Qt::DockWidgetArea>(i << 2), dw);
                                      }
                                      readSettings();
                                  }
                                  
                                  MainWindow::~MainWindow()
                                  {
                                      writeSettings();
                                      delete ui;
                                  }
                                  
                                  void MainWindow::readSettings()
                                  {
                                      const QSettings s("Test", "DockWidgetGeometry");
                                      if (!s.contains("MainWindowState"))
                                          return;
                                  
                                      const QByteArray array = s.value("MainWindowState").toByteArray();
                                      restoreState(array);
                                  }
                                  
                                  void MainWindow::writeSettings() const
                                  {
                                      QSettings s("Test", "DockWidgetGeometry");
                                      s.setValue("MainWindowState", saveState());
                                  }
                                  

                                  main.cpp

                                  #include "mainwindow.h"
                                  
                                  #include <QApplication>
                                  
                                  int main(int argc, char *argv[])
                                  {
                                      QApplication a(argc, argv);
                                      MainWindow w;
                                      w.show();
                                      return a.exec();
                                  }
                                  

                                  I start the application, move all dock widgets to the left dock, join two as floating tabs, change their sizes. Whatever I do is exactly recovered after closing and re-starting the app.

                                  22674419-3425-4bb8-adbb-9b35f1c08c49-image.png

                                  So I suspect that your application touches the docked dockwidgets' size after the state is restored.

                                  Cheers
                                  Axel

                                  PerdrixP Offline
                                  PerdrixP Offline
                                  Perdrix
                                  wrote on last edited by
                                  #16

                                  @Axel-Spoerl The only code I have the messes with its size is in SetupUi, and that is done before the code that tries to restore its size.

                                      void setupUi(QDockWidget *PictureList)
                                      {
                                          if (PictureList->objectName().isEmpty())
                                              PictureList->setObjectName("PictureList");
                                          PictureList->resize(618, 156);
                                          QSizePolicy sizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
                                          sizePolicy.setHorizontalStretch(0);
                                          sizePolicy.setVerticalStretch(0);
                                          sizePolicy.setHeightForWidth(PictureList->sizePolicy().hasHeightForWidth());
                                          PictureList->setSizePolicy(sizePolicy);
                                          PictureList->setMinimumSize(QSize(618, 156));
                                          PictureList->setStyleSheet(QString::fromUtf8(""));
                                          PictureList->setFeatures(QDockWidget::DockWidgetFloatable|QDockWidget::DockWidgetMovable);
                                          PictureList->setAllowedAreas(Qt::BottomDockWidgetArea|Qt::RightDockWidgetArea);
                                          PictureList->setWindowTitle(QString::fromUtf8("Light Frames: 0      -      Dark Frames: 0      -      Flat Frames: 0      -   Dark Flat Frames: 0   -      Offset/Bias Frames: 0"));
                                          dockWidgetContents = new QWidget();
                                          dockWidgetContents->setObjectName("dockWidgetContents");
                                          QSizePolicy sizePolicy1(QSizePolicy::Expanding, QSizePolicy::Expanding);
                                          sizePolicy1.setHorizontalStretch(0);
                                          sizePolicy1.setVerticalStretch(0);
                                          sizePolicy1.setHeightForWidth(dockWidgetContents->sizePolicy().hasHeightForWidth());
                                          dockWidgetContents->setSizePolicy(sizePolicy1);
                                          verticalLayout = new QVBoxLayout(dockWidgetContents);
                                          verticalLayout->setObjectName("verticalLayout");
                                          tableView = new QTableView(dockWidgetContents);
                                          tableView->setObjectName("tableView");
                                  
                                          verticalLayout->addWidget(tableView);
                                  
                                          tabBar = new QTabBar(dockWidgetContents);
                                          tabBar->setObjectName("tabBar");
                                          QSizePolicy sizePolicy2(QSizePolicy::Expanding, QSizePolicy::Minimum);
                                          sizePolicy2.setHorizontalStretch(0);
                                          sizePolicy2.setVerticalStretch(0);
                                          sizePolicy2.setHeightForWidth(tabBar->sizePolicy().hasHeightForWidth());
                                          tabBar->setSizePolicy(sizePolicy2);
                                          tabBar->setMinimumSize(QSize(0, 28));
                                          tabBar->setMaximumSize(QSize(16777215, 28));
                                  
                                          verticalLayout->addWidget(tabBar);
                                  
                                          PictureList->setWidget(dockWidgetContents);
                                  
                                          retranslateUi(PictureList);
                                  
                                          QMetaObject::connectSlotsByName(PictureList);
                                      } // setupUi
                                  

                                  What's more is that if the QSettings values for geometry and windowState aren't present, the only code that I have to adjust the size is at the start of the code I posted earlier where it does

                                  resizeDocks({ pictureList }, { 150 }, Qt::Vertical);
                                  

                                  and that appears to set the size just fine for the FIRST time open:

                                  8ecf38f6-9e36-437b-a5b3-b25cac6c19fb-image.png

                                  Subsequent opens always open to a large size that appears related to the main window size.

                                  PerdrixP 1 Reply Last reply
                                  0
                                  • PerdrixP Perdrix

                                    @Axel-Spoerl The only code I have the messes with its size is in SetupUi, and that is done before the code that tries to restore its size.

                                        void setupUi(QDockWidget *PictureList)
                                        {
                                            if (PictureList->objectName().isEmpty())
                                                PictureList->setObjectName("PictureList");
                                            PictureList->resize(618, 156);
                                            QSizePolicy sizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
                                            sizePolicy.setHorizontalStretch(0);
                                            sizePolicy.setVerticalStretch(0);
                                            sizePolicy.setHeightForWidth(PictureList->sizePolicy().hasHeightForWidth());
                                            PictureList->setSizePolicy(sizePolicy);
                                            PictureList->setMinimumSize(QSize(618, 156));
                                            PictureList->setStyleSheet(QString::fromUtf8(""));
                                            PictureList->setFeatures(QDockWidget::DockWidgetFloatable|QDockWidget::DockWidgetMovable);
                                            PictureList->setAllowedAreas(Qt::BottomDockWidgetArea|Qt::RightDockWidgetArea);
                                            PictureList->setWindowTitle(QString::fromUtf8("Light Frames: 0      -      Dark Frames: 0      -      Flat Frames: 0      -   Dark Flat Frames: 0   -      Offset/Bias Frames: 0"));
                                            dockWidgetContents = new QWidget();
                                            dockWidgetContents->setObjectName("dockWidgetContents");
                                            QSizePolicy sizePolicy1(QSizePolicy::Expanding, QSizePolicy::Expanding);
                                            sizePolicy1.setHorizontalStretch(0);
                                            sizePolicy1.setVerticalStretch(0);
                                            sizePolicy1.setHeightForWidth(dockWidgetContents->sizePolicy().hasHeightForWidth());
                                            dockWidgetContents->setSizePolicy(sizePolicy1);
                                            verticalLayout = new QVBoxLayout(dockWidgetContents);
                                            verticalLayout->setObjectName("verticalLayout");
                                            tableView = new QTableView(dockWidgetContents);
                                            tableView->setObjectName("tableView");
                                    
                                            verticalLayout->addWidget(tableView);
                                    
                                            tabBar = new QTabBar(dockWidgetContents);
                                            tabBar->setObjectName("tabBar");
                                            QSizePolicy sizePolicy2(QSizePolicy::Expanding, QSizePolicy::Minimum);
                                            sizePolicy2.setHorizontalStretch(0);
                                            sizePolicy2.setVerticalStretch(0);
                                            sizePolicy2.setHeightForWidth(tabBar->sizePolicy().hasHeightForWidth());
                                            tabBar->setSizePolicy(sizePolicy2);
                                            tabBar->setMinimumSize(QSize(0, 28));
                                            tabBar->setMaximumSize(QSize(16777215, 28));
                                    
                                            verticalLayout->addWidget(tabBar);
                                    
                                            PictureList->setWidget(dockWidgetContents);
                                    
                                            retranslateUi(PictureList);
                                    
                                            QMetaObject::connectSlotsByName(PictureList);
                                        } // setupUi
                                    

                                    What's more is that if the QSettings values for geometry and windowState aren't present, the only code that I have to adjust the size is at the start of the code I posted earlier where it does

                                    resizeDocks({ pictureList }, { 150 }, Qt::Vertical);
                                    

                                    and that appears to set the size just fine for the FIRST time open:

                                    8ecf38f6-9e36-437b-a5b3-b25cac6c19fb-image.png

                                    Subsequent opens always open to a large size that appears related to the main window size.

                                    PerdrixP Offline
                                    PerdrixP Offline
                                    Perdrix
                                    wrote on last edited by Perdrix
                                    #17

                                    @Perdrix Maybe I am trying to restore the geometry and window state at the wrong time? I am doing it in code invoked from showEvent()

                                    void DeepSkyStacker::showEvent(QShowEvent* event)
                                    {
                                    	if (!event->spontaneous())
                                    	{
                                    		if (!initialised)
                                    		{
                                    			initialised = true;
                                    			onInitialise();
                                    		}
                                    	}
                                    	// Invoke base class showEvent()
                                    	return Inherited::showEvent(event);
                                    }
                                    
                                    Axel SpoerlA 1 Reply Last reply
                                    0
                                    • PerdrixP Perdrix

                                      @Perdrix Maybe I am trying to restore the geometry and window state at the wrong time? I am doing it in code invoked from showEvent()

                                      void DeepSkyStacker::showEvent(QShowEvent* event)
                                      {
                                      	if (!event->spontaneous())
                                      	{
                                      		if (!initialised)
                                      		{
                                      			initialised = true;
                                      			onInitialise();
                                      		}
                                      	}
                                      	// Invoke base class showEvent()
                                      	return Inherited::showEvent(event);
                                      }
                                      
                                      Axel SpoerlA Online
                                      Axel SpoerlA Online
                                      Axel Spoerl
                                      Moderators
                                      wrote on last edited by
                                      #18

                                      @Perdrix
                                      Hi David,
                                      If I tweak the reproducer and override QMainWindow::showEvent(QShowEvent *event), it works as well.

                                      I don't know about the DeepSkyStacker class, where it inherits from and when its first non-spontaneuous show event is consumed. My gut feeling tells me to put some pocket money on the show event. It's an unusual place to call QMainWindow::restoreState(): Are the dock widgets are already constructed and added to the main window, when the show event is consumed? The dock widget part of the call will be a no-op, if the dock widgets aren't in place or don't have an object name.

                                      I'd happily look into the code of DSS, because it's a great piece of software (have I ever mentioned that? Apologies if I haven't). It's a VS project, however, and I only use Qt Creator.

                                      I'd try the following:

                                      • play with the reproducer in my earlier post, to see if the issue can be isolated
                                      • play with the dock widgets: Tab them, undock them, close and restart the app => see if anything is restored at all.
                                      • move the the code calling QMainWindow::restoreState() right after the construction of the dock widgets.

                                      Cheers
                                      Axel

                                      Software Engineer
                                      The Qt Company, Oslo

                                      PerdrixP 1 Reply Last reply
                                      0
                                      • Axel SpoerlA Axel Spoerl

                                        @Perdrix
                                        Hi David,
                                        If I tweak the reproducer and override QMainWindow::showEvent(QShowEvent *event), it works as well.

                                        I don't know about the DeepSkyStacker class, where it inherits from and when its first non-spontaneuous show event is consumed. My gut feeling tells me to put some pocket money on the show event. It's an unusual place to call QMainWindow::restoreState(): Are the dock widgets are already constructed and added to the main window, when the show event is consumed? The dock widget part of the call will be a no-op, if the dock widgets aren't in place or don't have an object name.

                                        I'd happily look into the code of DSS, because it's a great piece of software (have I ever mentioned that? Apologies if I haven't). It's a VS project, however, and I only use Qt Creator.

                                        I'd try the following:

                                        • play with the reproducer in my earlier post, to see if the issue can be isolated
                                        • play with the dock widgets: Tab them, undock them, close and restart the app => see if anything is restored at all.
                                        • move the the code calling QMainWindow::restoreState() right after the construction of the dock widgets.

                                        Cheers
                                        Axel

                                        PerdrixP Offline
                                        PerdrixP Offline
                                        Perdrix
                                        wrote on last edited by Perdrix
                                        #19

                                        @Axel-Spoerl The widgets are also constructed in onInitialise().

                                        You suggest that showEvent() is an unusual place from which to call restoreState(). Where would you normally put it? At the end of the ctor as you did in you small example?

                                        Axel SpoerlA 1 Reply Last reply
                                        0
                                        • PerdrixP Perdrix

                                          @Axel-Spoerl The widgets are also constructed in onInitialise().

                                          You suggest that showEvent() is an unusual place from which to call restoreState(). Where would you normally put it? At the end of the ctor as you did in you small example?

                                          Axel SpoerlA Online
                                          Axel SpoerlA Online
                                          Axel Spoerl
                                          Moderators
                                          wrote on last edited by
                                          #20

                                          @Perdrix said in Preserving/Restoring QDockWidget size:

                                          At the end of the ctor as you did in you small example?

                                          The c'tor is definitely a good spot, but it has to be called after the dock widgets are fully created.

                                          Software Engineer
                                          The Qt Company, Oslo

                                          PerdrixP 1 Reply Last reply
                                          0

                                          • Login

                                          • Login or register to search.
                                          • First post
                                            Last post
                                          0
                                          • Categories
                                          • Recent
                                          • Tags
                                          • Popular
                                          • Users
                                          • Groups
                                          • Search
                                          • Get Qt Extensions
                                          • Unsolved