Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Saving QTableView state
Qt 6.12 LTS is out! See what's new in the release blog

Saving QTableView state

Scheduled Pinned Locked Moved Solved General and Desktop
12 Posts 4 Posters 2.7k 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
    #3

    I sub-classed QTableView:

    #include <QTableView>
    
    class QCloseEvent;
    class QContextMenuEvent;
    
    namespace DSS
    {
        class TableView :
            public QTableView
        {
            typedef QTableView
                Inherited;
    
            Q_OBJECT
    
        public:
            explicit TableView(QWidget* parent = nullptr);
    
            ~TableView() noexcept
            {
            }
    
        protected:
            void closeEvent([[maybe_unused]] QCloseEvent* e) override;
    
            void contextMenuEvent([[maybe_unused]] QContextMenuEvent* event) override;
        };
    }
    

    and in the cpp file:

    TableView::TableView(QWidget* parent) :
    	QTableView{ parent }
    {
    	QSettings settings;
    	horizontalHeader()->restoreState(
    		settings.value("Dialogs/StackingDlg/TableView/HorizontalHeader/windowState").toByteArray());
    }
    
    void TableView::closeEvent([[maybe_unused]] QCloseEvent* e)
    {
    	QSettings settings;
    	settings.setValue("Dialogs/StackingDlg/TableView/HorizontalHeader/windowState", 
    		horizontalHeader()->saveState());
    }
    
    void TableView::contextMenuEvent([[maybe_unused]] QContextMenuEvent* e)
    {
    	QMenu menu(this);
    
    	menu.exec(e->globalPos());
    }
    

    But the closeEvent mf was not called (placed a breakpoint in there)??? (The ctor was invoked)

    What am I doing wrong?

    Thanks
    David

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

      Hi,

      Your error is to assume that all widgets get a close event. That's not the case. It's the case for the top level widget but not for its children.

      Also, the saving and loading of setting should rather be handled by the widget that manages it.

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

      1 Reply Last reply
      1
      • PerdrixP Offline
        PerdrixP Offline
        Perdrix
        wrote on last edited by Perdrix
        #5

        So does that mean only the QMainWindow gets a closeEvent, or that if the TableView is a child of a Widget called StackingDlg, that it will get a closeEvent() ?

        In this case the StackingDlg is someway down the hierarchy from QMainWindow:

        	widget = new QWidget(this);
        	widget->setObjectName("centralWidget");
        	setCentralWidget(widget);
        
        	QHBoxLayout* horizontalLayout{ new QHBoxLayout(widget) };
        	widget->setLayout(horizontalLayout);
        	ZTRACE_RUNTIME("Creating Horizontal Splitter");
        	splitter = new QSplitter(Qt::Horizontal, widget);
        	splitter->setObjectName("splitter");
        
        	ZTRACE_RUNTIME("Creating Explorer Bar (Left Panel)");
        	explorerBar = new ExplorerBar(widget);
        	explorerBar->setObjectName("explorerBar");
        	splitter->addWidget(explorerBar);
        
        	ZTRACE_RUNTIME("Creating stackedWidget");
        	stackedWidget = new QStackedWidget(splitter);
        	stackedWidget->setObjectName("stackedWidget");
        	splitter->addWidget(stackedWidget);
        
        	ZTRACE_RUNTIME("Creating Stacking Panel");
        	stackingDlg = new DSS::StackingDlg(widget);
        	stackingDlg->setObjectName("stackingDlg");
        
        	ZTRACE_RUNTIME("Adding Stacking Panel to stackedWidget");
        	stackedWidget->addWidget(stackingDlg);
        
        	winHost = new QWinHost(stackedWidget);
        	winHost->setObjectName("winHost");
        	stackedWidget->addWidget(winHost);
        
        	ZTRACE_RUNTIME("Creating Processing Panel");
        	BOOL result = processingDlg.Create(IDD_PROCESSING);
        	//processingDlg.OnInitDialog();
        
        	HWND hwnd{ processingDlg.GetSafeHwnd() };
        	Q_ASSERT(NULL != hwnd);
        	winHost->setWindow(hwnd);
        
        	splitter->setStretchFactor(1, 1);		// Want Stacking part to take any spare space.
        
        	horizontalLayout->addWidget(splitter);
        
        1 Reply Last reply
        0
        • PerdrixP Perdrix

          I sub-classed QTableView:

          #include <QTableView>
          
          class QCloseEvent;
          class QContextMenuEvent;
          
          namespace DSS
          {
              class TableView :
                  public QTableView
              {
                  typedef QTableView
                      Inherited;
          
                  Q_OBJECT
          
              public:
                  explicit TableView(QWidget* parent = nullptr);
          
                  ~TableView() noexcept
                  {
                  }
          
              protected:
                  void closeEvent([[maybe_unused]] QCloseEvent* e) override;
          
                  void contextMenuEvent([[maybe_unused]] QContextMenuEvent* event) override;
              };
          }
          

          and in the cpp file:

          TableView::TableView(QWidget* parent) :
          	QTableView{ parent }
          {
          	QSettings settings;
          	horizontalHeader()->restoreState(
          		settings.value("Dialogs/StackingDlg/TableView/HorizontalHeader/windowState").toByteArray());
          }
          
          void TableView::closeEvent([[maybe_unused]] QCloseEvent* e)
          {
          	QSettings settings;
          	settings.setValue("Dialogs/StackingDlg/TableView/HorizontalHeader/windowState", 
          		horizontalHeader()->saveState());
          }
          
          void TableView::contextMenuEvent([[maybe_unused]] QContextMenuEvent* e)
          {
          	QMenu menu(this);
          
          	menu.exec(e->globalPos());
          }
          

          But the closeEvent mf was not called (placed a breakpoint in there)??? (The ctor was invoked)

          What am I doing wrong?

          Thanks
          David

          M Offline
          M Offline
          mpergand
          wrote on last edited by mpergand
          #6

          @Perdrix said in Saving QTableView state:

          I sub-classed QTableView:

          No need to subclass, neither for save/restore state, nor for context menu.

          As @SGaist said, do the all thing in the top level widget.
          showEvent and closeEvent for the state,
          and use customContextMenuRequested signal, see setContextMenuPolicy().

          1 Reply Last reply
          0
          • PerdrixP Offline
            PerdrixP Offline
            Perdrix
            wrote on last edited by Perdrix
            #7

            Hmmm the closeEvent() of StackingDlg also doesn't get triggered.

            It's a royal mess to access the tableView from the closeEvent of the QMainWindow.

            Would the destroy() mf for StackingDlg (which owns the QTableView) be a good location to save the horizontal header state for the table view?

            UPDATE! Arrgh QWidget::destroy() isn't virtual so I can't use that!

            So what can I use simply to detect the one of my Widgets is going away.

            PS setting the context menu policy for the table view to Qt::CustomContextMenu and having:

            void StackingDlg::on_tableView_customContextMenuRequested(const QPoint& pos)
            

            is a really nice way to handle the popup menu!

            Thanks
            David

            M 1 Reply Last reply
            0
            • PerdrixP Perdrix

              Hmmm the closeEvent() of StackingDlg also doesn't get triggered.

              It's a royal mess to access the tableView from the closeEvent of the QMainWindow.

              Would the destroy() mf for StackingDlg (which owns the QTableView) be a good location to save the horizontal header state for the table view?

              UPDATE! Arrgh QWidget::destroy() isn't virtual so I can't use that!

              So what can I use simply to detect the one of my Widgets is going away.

              PS setting the context menu policy for the table view to Qt::CustomContextMenu and having:

              void StackingDlg::on_tableView_customContextMenuRequested(const QPoint& pos)
              

              is a really nice way to handle the popup menu!

              Thanks
              David

              M Offline
              M Offline
              mpergand
              wrote on last edited by
              #8

              @Perdrix said in Saving QTableView state:

              It's a royal mess to access the tableView from the closeEvent of the QMainWindow.

              Why ?

              stackingDlg = new DSS::StackingDlg(widget);
              stackingDlg->setObjectName("stackingDlg");
              

              stackingDlg not a variable of your mainWindow ?
              you can even retrieve it by its name ;)

              1 Reply Last reply
              0
              • PerdrixP Offline
                PerdrixP Offline
                Perdrix
                wrote on last edited by Perdrix
                #9

                Arrghh forgot I was saving that in the class !!!

                Except of course ui is private in DSS:StackingDlg. So I had to make the main window a friend of DSS::StackingDlg

                And it worked fine

                Thanks all
                D.

                1 Reply Last reply
                0
                • PerdrixP Offline
                  PerdrixP Offline
                  Perdrix
                  wrote on last edited by Perdrix
                  #10

                  The final code to save the state of the Horizontal header in the QMainWindow::closeEvent handler reads like this:

                  QSettings settings;
                  settings.setValue("geometry", saveGeometry());
                  settings.setValue("windowState", saveState());
                  QTableView* tableView = this->findChild<QTableView*>("tableView");
                  settings.setValue("Dialogs/StackingDlg/TableView/HorizontalHeader/windowState",
                  	tableView->horizontalHeader()->saveState());
                  

                  it relies on the tableView object being named but that is normally true.
                  David

                  JonBJ 1 Reply Last reply
                  1
                  • PerdrixP Perdrix

                    The final code to save the state of the Horizontal header in the QMainWindow::closeEvent handler reads like this:

                    QSettings settings;
                    settings.setValue("geometry", saveGeometry());
                    settings.setValue("windowState", saveState());
                    QTableView* tableView = this->findChild<QTableView*>("tableView");
                    settings.setValue("Dialogs/StackingDlg/TableView/HorizontalHeader/windowState",
                    	tableView->horizontalHeader()->saveState());
                    

                    it relies on the tableView object being named but that is normally true.
                    David

                    JonBJ Offline
                    JonBJ Offline
                    JonB
                    wrote on last edited by JonB
                    #11

                    @Perdrix said in Saving QTableView state:

                    it relies on the tableView object being named but is normally true.

                    Is this a statement about what you are "happy" with as your behaviour, or something you might like improved? Just a couple of comments:

                    • IF you have only one table view then (are you aware that) you can omit the object name and just go this->findChild<QTableView*>(), so you do not have to set any object name on it?

                    • If you have more than one, which one are you looking for to be saved under Dialogs/StackingDlg/TableView/HorizontalHeader/windowState?

                    • Instead of relying on the object name, you might consider adding a property to the/those table view(s) to indicate this is/should be "saved", and search among all table views for that/those which have this property.

                    • Of course, you could also subclass the QTableView to, say, a QSaveableTableView and search for that class.

                    PerdrixP 1 Reply Last reply
                    1
                    • JonBJ JonB

                      @Perdrix said in Saving QTableView state:

                      it relies on the tableView object being named but is normally true.

                      Is this a statement about what you are "happy" with as your behaviour, or something you might like improved? Just a couple of comments:

                      • IF you have only one table view then (are you aware that) you can omit the object name and just go this->findChild<QTableView*>(), so you do not have to set any object name on it?

                      • If you have more than one, which one are you looking for to be saved under Dialogs/StackingDlg/TableView/HorizontalHeader/windowState?

                      • Instead of relying on the object name, you might consider adding a property to the/those table view(s) to indicate this is/should be "saved", and search among all table views for that/those which have this property.

                      • Of course, you could also subclass the QTableView to, say, a QSaveableTableView and search for that class.

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

                      @JonB said in Saving QTableView state:

                      Is this a statement about what you are "happy" with

                      Yes, I am happy with the normal default behaviour.

                      I wasn't aware of all the stuff in your reply, but all are useful bits of information.

                      I only have one table view to worry about :)

                      Thanks
                      D.

                      1 Reply Last reply
                      1

                      • Login

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