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. Unable to restore floating QToolBar via QSettings

Unable to restore floating QToolBar via QSettings

Scheduled Pinned Locked Moved Solved General and Desktop
5 Posts 2 Posters 1.9k Views
  • 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.
  • ErikaE Offline
    ErikaE Offline
    Erika
    wrote on last edited by
    #1

    I've tried a number of different approaches, and feel like there should be something simpler that I'm missing. I've searched the forums, but to no avail.

    If you run the following (and any of the three attempts to correct the issue), load the program up, have the second toolbar be positioned and floating, switch to "View 1" (which doesn't need toolbar 2, so it should be removed), close the program and restart. The toolbar 2 (if visible) is in the wrong spot. It works fine for dock widgets.

    Any suggestions? Thoughts?

    // qt includes
    #include <QtWidgets\QMainWindow>
    #include <QtWidgets\QApplication>
    #include <QtWidgets\QToolBar>
    #include <QtWidgets\QDockWidget>
    #include <QtCore\QSettings>
    
    class MyMainWindow : public QMainWindow
    {
    public:
    	MyMainWindow(QWidget* parent = nullptr) : QMainWindow(parent)
    	{
    		// setup main window
    		setCentralWidget(new QWidget(this));
    
    		// toolbar 1 setup
    		toolbar1 = new QToolBar("Toolbar 1");
    		toolbar1->setObjectName("Toolbar 1");
    		addToolBar(Qt::TopToolBarArea, toolbar1);
    		for ( int i = 0; i < 3; i++ )
    			toolbar1->addAction("TB1_" + QString::number(i), []() {});
    
    		// toolbar 2
    		toolbar2 = new QToolBar("Toolbar 2");
    		toolbar2->setObjectName("Toolbar 2");
    		addToolBar(Qt::TopToolBarArea, toolbar2);
    		for ( int i = 0; i < 5; i++ )
    			toolbar2->addAction("TB2_" + QString::number(i), []() {});
    
    		// dock examples
    		dock1 = new QDockWidget("Dock 1", this);
    		dock1->setObjectName("Dock 1");
    		addDockWidget(Qt::LeftDockWidgetArea, dock1);
    		dock2 = new QDockWidget("Dock 2", this);
    		dock2->setObjectName("Dock 2");
    		addDockWidget(Qt::LeftDockWidgetArea, dock2);
    
    		// *** CRUX OF ISSUES *** //
    		// setup toolbar 1 calls
    		toolbar1->addAction("View 1", [this]()
    		{
    			// attempt 1 - use remove/custom 'restore'? bad placement
    			//removeToolBar(toolbar2); // unsure what to pair this with
    
    			// attempt 2 - use QSettings?
    			//// save current location of toolbar
    			//QSettings settings;
    			//settings.setValue(toolbar2->objectName(), toolbar2->saveGeometry()); // not right - does top-level/all widgets
    			//toolbar2->setHidden(true); // doesn't work for the context menu (even if custom)
    
    			// attempt 3 - custom use of QSettings? very buggy...
    			QSettings settings;
    			settings.setValue(toolbar2->objectName() + "_floating", toolbar2->isFloating());
    			settings.setValue(toolbar2->objectName() + "_geometry", toolbar2->geometry());
    			settings.setValue(toolbar2->objectName() + "_visible", toolbar2->isVisible());
    			settings.setValue(toolbar2->objectName() + "_toolbararea", (unsigned)this->toolBarArea(toolbar2));
    			removeToolBar(toolbar2);
    
    			// dock example - works fine!
    			removeDockWidget(dock2);
    		});
    		QAction* defaultView = toolbar1->addAction("View 2", [this]()
    		{
    			// attempt 1 - use remove/custom 'restore'? bad placement
    			//addToolBar(toolbar2);
    			//toolbar2->show(); // has bad placement
    
    			// attempt 2 - use QSettings?
    			//// restore location of toolbar
    			//QSettings settings;
    			//toolbar2->restoreGeometry(settings.value(toolbar2->objectName()).toByteArray()); // not right - does top-level/all widgets
    			//toolbar2->setHidden(false); // doesn't work for the context menu (even if custom)
    
    			// attempt 3 - custom use of QSettings? very buggy...
    			QSettings settings;
    			Qt::ToolBarArea area = ( Qt::ToolBarArea )settings.value(toolbar2->objectName() + "_toolbararea").toUInt();
    			addToolBar(area, toolbar2); // not right - may re-order toolbars
    			toolbar2->setVisible(settings.value(toolbar2->objectName() + "_visible").toBool());
    			bool isFloating = settings.value(toolbar2->objectName() + "_floating").toBool();
    			if ( isFloating )
    				toolbar2->setWindowFlags(toolbar2->windowFlags() | Qt::FramelessWindowHint);
    			toolbar2->setGeometry(settings.value(toolbar2->objectName() + "_geometry").toRect());
    
    			// dock example - works fine!
    			restoreDockWidget(dock2);
    		});
    		// *** END CRUX OF ISSUES *** //
    
    		QAction* quitAction = toolbar1->addAction("Quit", [this]() { this->close(); });
    		quitAction->setShortcut(Qt::Key_Q);
    
    		resize(1200, 800);
    
    		// its all setup - restore prior state
    		LoadUI();
    
    		// load default view
    		defaultView->trigger();
    	}
    
    	void LoadUI()
    	{
    		// load settings from registry
    		QSettings settings;
    		QString sQState = "windowState";
    		bool hasSettings = settings.contains(sQState);
    		if ( hasSettings )
    			restoreState(settings.value(sQState).toByteArray());
    		QString sQGeometry = "windowGeometry";
    		hasSettings = settings.contains(sQGeometry);
    		if ( hasSettings )
    			restoreGeometry(settings.value(sQGeometry).toByteArray());
    	}
    
    	void closeEvent(QCloseEvent* event)
    	{
    		QSettings settings;
    		QString sQState = "windowState";
    		settings.setValue(sQState, saveState());
    		QString sQGeometry = "windowGeometry";
    		settings.setValue(sQGeometry, saveGeometry());
    	}
    
    private:
    	QToolBar *toolbar1, *toolbar2;
    	QDockWidget *dock1, *dock2;
    };
    
    int main( int argc, char *argv[] )
    {
    	// setup application
    	QApplication app( argc, argv );
    	app.setOrganizationName("QtExample");
    	app.setApplicationName("ToolBarSettingsBug");
    
    	// setup main window
    	MyMainWindow mainWin;
    
    	mainWin.show();
    	return app.exec();
    }
    
    1 Reply Last reply
    0
    • kshegunovK Offline
      kshegunovK Offline
      kshegunov
      Moderators
      wrote on last edited by kshegunov
      #2

      I'd suggest something along those lines:

      MyMainWindow::MyMainWindow(QWidget * parent = Q_NULLPTR)
          : QMainWindow(parent);
      {
          // ...
          toolbar1->addAction("View 1", [this]()  {
              restoreView("View1");
          });
          toolbar1->addAction("View 2", [this]()  {
              restoreView("View2");
          });
          // ...
      }
      
      void MyMainWindow::restoreView(const QString & name)
      {
          currentView = name; //< currentView is a QString and is only to keep track of the currently shown view
          QString key = QStringLiteral("%1/State").arg(name);
      
          QSettings settings;
          if (settings.contains(key))
              restoreState(settings.value(key).toByteArray());
      }
      
      void MyMainWindow::closeEvent(QCloseEvent * event)
      {
          QString key = QStringLiteral("%1/State").arg(currentView);
      
          QSettings settings;
          settings.setValue(key, saveState());
          // Save the geometry ...
      
          QMainWindow::closeEvent(event);
      }
      

      PS:
      And people mock me for my aversion to lambdas ... go figure ...

      Read and abide by the Qt Code of Conduct

      1 Reply Last reply
      0
      • ErikaE Offline
        ErikaE Offline
        Erika
        wrote on last edited by Erika
        #3

        Thanks @kshegunov for the suggestion. I understand where you're going with that, unfortunately I believe eg. if you resize the window on one view, it will restore the old window size when you switch views. ie. that more customized QSettings logic would be needed.

        Any other ideas?

        Anyone know why there isn't a restoreToolBar(...) function akin to restoreDockWidget(...)?


        Edit Addition: Though I notice you're only saving/restoring the state (so the window size is a bad example), it does mean the geometry will be inconsistent between views...

        kshegunovK 1 Reply Last reply
        0
        • ErikaE Erika

          Thanks @kshegunov for the suggestion. I understand where you're going with that, unfortunately I believe eg. if you resize the window on one view, it will restore the old window size when you switch views. ie. that more customized QSettings logic would be needed.

          Any other ideas?

          Anyone know why there isn't a restoreToolBar(...) function akin to restoreDockWidget(...)?


          Edit Addition: Though I notice you're only saving/restoring the state (so the window size is a bad example), it does mean the geometry will be inconsistent between views...

          kshegunovK Offline
          kshegunovK Offline
          kshegunov
          Moderators
          wrote on last edited by kshegunov
          #4

          @Erika said in Unable to restore floating QToolBar via QSettings:

          it does mean the geometry will be inconsistent between views...

          Inconsistent how? If you need the geometry to be tied to the view, then you just need to add a couple of lines to save/restore it, but I'd think this is a bad idea.

          Anyone know why there isn't a restoreToolBar(...) function akin to restoreDockWidget(...)?

          Probably because toolbars don't have a real state as the dock widgets. They're tied to a side of the window and nothing more, they don't have their own independent geometry, but depend on the geometry of the main window, and they aren't floating around as far as I remember.

          Seems I err. It's been some time since I've worked with GUIs.

          Read and abide by the Qt Code of Conduct

          1 Reply Last reply
          0
          • ErikaE Offline
            ErikaE Offline
            Erika
            wrote on last edited by
            #5

            Thanks @kshegunov for the response. We've decided to directly use a combination of setVisible/setHidden instead of removeToolBar, and manually track floating visibility of toolbars for re-loading the ui.

            I've also logged a bug: https://bugreports.qt.io/browse/QTBUG-58095 to address floating, hidden toolbars not being able to readily restore state unlike their dock widget counterparts.

            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