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. Detach tabs from QTabWidget and restore them
QtWS25 Last Chance

Detach tabs from QTabWidget and restore them

Scheduled Pinned Locked Moved Solved General and Desktop
11 Posts 3 Posters 3.6k 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.
  • M Offline
    M Offline
    Mark81
    wrote on last edited by
    #1

    I have a QTabWidget with the tabsClosable set to true.
    My goal is to "detach" a tab when the related close button is clicked. The tab should be removed and the content placed into a QDialog. Then when this dialog is closed the tab and its content should be restored in the tab bar in the same position. Please note that this must work for all tabs, until only one remain (in that case I disable the tabsClosable property).

    Here what I did so far:

    // DialogPopup is just an empty QDialog
    QMap<QString, DialogPopup *> _mapPopup;
    
    void MainWindow::tabView_tabCloseRequested(int index)
    {
        ui->tabView->tabBar()->removeTab(index);
        QString name = ui->tabView->tabText(index);
    
        DialogPopup *widget = new DialogPopup();
        widget->setWindowTitle(name);
        widget->setLayout(ui->tabView->widget(index)->layout()); // <--- it's correct?
        widget->show();
        connect(widget, &DialogPopup::finished, this, &MainWindow::popup_finished);
        _mapPopup[name] = widget;
    }
    
    void MainWindow::popup_finished(int result)
    {
        Q_UNUSED(result);
    
        DialogPopup *widget = qobject_cast<DialogPopup *>(sender());
        Q_ASSERT(widget);
    
        if (widget)
        {
            QString name = widget->windowTitle();
            ui->tabView->addTab(widget, name);
            delete widget; // <---- it's correct?
            _mapPopup.remove(name);
        }
    }
    

    It doesn't work well and I'm afraid I'm messing up all the pointers :-)

    Questions:

    1. to "copy" the contents to the dialog, it's correct to just set the layout to the pointer of the tab's layout?
    2. to restore the contents, I'm afraid I'm completely wrong... actually the original widgets are still there... how to retrieve them?
    3. how to restore the tabs in the initial order, even when a lot of them were detached?
    JonBJ 1 Reply Last reply
    0
    • M Mark81

      I have a QTabWidget with the tabsClosable set to true.
      My goal is to "detach" a tab when the related close button is clicked. The tab should be removed and the content placed into a QDialog. Then when this dialog is closed the tab and its content should be restored in the tab bar in the same position. Please note that this must work for all tabs, until only one remain (in that case I disable the tabsClosable property).

      Here what I did so far:

      // DialogPopup is just an empty QDialog
      QMap<QString, DialogPopup *> _mapPopup;
      
      void MainWindow::tabView_tabCloseRequested(int index)
      {
          ui->tabView->tabBar()->removeTab(index);
          QString name = ui->tabView->tabText(index);
      
          DialogPopup *widget = new DialogPopup();
          widget->setWindowTitle(name);
          widget->setLayout(ui->tabView->widget(index)->layout()); // <--- it's correct?
          widget->show();
          connect(widget, &DialogPopup::finished, this, &MainWindow::popup_finished);
          _mapPopup[name] = widget;
      }
      
      void MainWindow::popup_finished(int result)
      {
          Q_UNUSED(result);
      
          DialogPopup *widget = qobject_cast<DialogPopup *>(sender());
          Q_ASSERT(widget);
      
          if (widget)
          {
              QString name = widget->windowTitle();
              ui->tabView->addTab(widget, name);
              delete widget; // <---- it's correct?
              _mapPopup.remove(name);
          }
      }
      

      It doesn't work well and I'm afraid I'm messing up all the pointers :-)

      Questions:

      1. to "copy" the contents to the dialog, it's correct to just set the layout to the pointer of the tab's layout?
      2. to restore the contents, I'm afraid I'm completely wrong... actually the original widgets are still there... how to retrieve them?
      3. how to restore the tabs in the initial order, even when a lot of them were detached?
      JonBJ Online
      JonBJ Online
      JonB
      wrote on last edited by
      #2

      @Mark81
      I don't know the answer to all your stuff, but if you are having issues detaching & restoring the tab then why do you not instead just hide & later re-show it?

      M 1 Reply Last reply
      0
      • JonBJ JonB

        @Mark81
        I don't know the answer to all your stuff, but if you are having issues detaching & restoring the tab then why do you not instead just hide & later re-show it?

        M Offline
        M Offline
        Mark81
        wrote on last edited by
        #3

        @JonB because I didn't find the right way to do this. I'm able to hide the tab's content with ui->tabView->widget(index)->hide(), but the tab it's still there. I don't understand how to hide the tab, I can just remove it - and I'm aware the content is not destroyed.

        JonBJ 1 Reply Last reply
        1
        • M Mark81

          @JonB because I didn't find the right way to do this. I'm able to hide the tab's content with ui->tabView->widget(index)->hide(), but the tab it's still there. I don't understand how to hide the tab, I can just remove it - and I'm aware the content is not destroyed.

          JonBJ Online
          JonBJ Online
          JonB
          wrote on last edited by JonB
          #4

          @Mark81
          I did not realise that. In which case e.g. https://stackoverflow.com/questions/18394706/show-hide-sub-tab-on-qtabwidget shows an example using removeTab followed by later insertTab (not addTab) to restore it in the correct original place.

          1 Reply Last reply
          0
          • M Offline
            M Offline
            Mark81
            wrote on last edited by Mark81
            #5

            My code contains the remove tab method, and the pointer to the content's widget should be "stored" into the dialog's one.
            I cannot just insert the tab in the original place because the index might be changed (see question 3).
            For example, this is the initial situation:

            0 ABC, 1 DEF, 2 GHI, 3 JKL

            now I detach tab 1, storing its index in a dialog's property:

            0 ABC, 1 GHI, 2 JKL

            now I detach tab 0, storing its index in a dialog's property:

            0 GHI, 1 JKL

            well, now the dialog DEF has stored the index 1, and ABC index 0.
            If I try to restore tab DEF using insertTab it will placed at index 1 but it's wrong because DEF should be before GHI.

            J.HilkJ 1 Reply Last reply
            0
            • M Mark81

              My code contains the remove tab method, and the pointer to the content's widget should be "stored" into the dialog's one.
              I cannot just insert the tab in the original place because the index might be changed (see question 3).
              For example, this is the initial situation:

              0 ABC, 1 DEF, 2 GHI, 3 JKL

              now I detach tab 1, storing its index in a dialog's property:

              0 ABC, 1 GHI, 2 JKL

              now I detach tab 0, storing its index in a dialog's property:

              0 GHI, 1 JKL

              well, now the dialog DEF has stored the index 1, and ABC index 0.
              If I try to restore tab DEF using insertTab it will placed at index 1 but it's wrong because DEF should be before GHI.

              J.HilkJ Offline
              J.HilkJ Offline
              J.Hilk
              Moderators
              wrote on last edited by
              #6

              @Mark81 There's a bit of logic involved but I'll outline it for you.

              You could, before the first tab removal create a QVector<QWidget*> widgetsInOrder

              than when you try to insert it back into the tabwidget, go through that vector, until you find your current widget pointer.
              go one widget back in the list, and use int QTabWidget::indexOf(QWidget *w) const that index +1 is where you want to insert the widget back in.

              if the returned index is -1 than that widget is also removed from the tabwidget and you have to go one widget more back in the list.


              Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


              Q: What's that?
              A: It's blue light.
              Q: What does it do?
              A: It turns blue.

              M 1 Reply Last reply
              0
              • J.HilkJ J.Hilk

                @Mark81 There's a bit of logic involved but I'll outline it for you.

                You could, before the first tab removal create a QVector<QWidget*> widgetsInOrder

                than when you try to insert it back into the tabwidget, go through that vector, until you find your current widget pointer.
                go one widget back in the list, and use int QTabWidget::indexOf(QWidget *w) const that index +1 is where you want to insert the widget back in.

                if the returned index is -1 than that widget is also removed from the tabwidget and you have to go one widget more back in the list.

                M Offline
                M Offline
                Mark81
                wrote on last edited by
                #7

                @J.Hilk Got it. I'll try this way, thanks! What about question 1 and 2? It's correct to set the layout (which in turn contains the widgets) to the dialog?

                JonBJ J.HilkJ 2 Replies Last reply
                0
                • M Mark81

                  @J.Hilk Got it. I'll try this way, thanks! What about question 1 and 2? It's correct to set the layout (which in turn contains the widgets) to the dialog?

                  JonBJ Online
                  JonBJ Online
                  JonB
                  wrote on last edited by JonB
                  #8

                  @Mark81
                  I may be wrong(!), but I cannot believe it can be right to delete widget immediately after you have added it back as a tab? Adding widget as tab may re-parent it to the QTabView, but I don't believe that will copy/new it, so you mustn't delete it?

                  1 Reply Last reply
                  0
                  • M Mark81

                    @J.Hilk Got it. I'll try this way, thanks! What about question 1 and 2? It's correct to set the layout (which in turn contains the widgets) to the dialog?

                    J.HilkJ Offline
                    J.HilkJ Offline
                    J.Hilk
                    Moderators
                    wrote on last edited by
                    #9

                    @Mark81 said in Detach tabs from QTabWidget and restore them:

                    What about question 1 and 2? It's correct to set the layout (which in turn contains the widgets) to the dialog?

                    Removing a Widget and passing it to an other Layout is usually how one "moves" widgets around, yes :-)


                    Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


                    Q: What's that?
                    A: It's blue light.
                    Q: What does it do?
                    A: It turns blue.

                    M 1 Reply Last reply
                    0
                    • J.HilkJ J.Hilk

                      @Mark81 said in Detach tabs from QTabWidget and restore them:

                      What about question 1 and 2? It's correct to set the layout (which in turn contains the widgets) to the dialog?

                      Removing a Widget and passing it to an other Layout is usually how one "moves" widgets around, yes :-)

                      M Offline
                      M Offline
                      Mark81
                      wrote on last edited by
                      #10

                      @J.Hilk said in Detach tabs from QTabWidget and restore them:

                      Removing a Widget and passing it to an other Layout is usually how one "moves" widgets around, yes :-)

                      Unfortunately I'm still doing it wrong. Let's see this short function:

                      void MainWindow::tabView_tabCloseRequested(int index)
                      {
                          QString name = ui->tabView->tabText(index); // retrieve the name of the tab
                          QLayout *layout = ui->tabView->widget(index)->layout(); // temporary save the pointer to the content
                          ui->tabView->tabBar()->removeTab(index); // remove the tab (now we have only the pointer above to its content)
                      
                          DialogPopup *widget = new DialogPopup(); // create a new Dialog
                          widget->setWindowTitle(name); // set the title like the name of the tab removed
                          widget->setLayout(layout); // place here the content of the tab removed
                          widget->show(); // show the dialog
                      }
                      

                      The dialog is created with the correct content, but the downside is it clears the content of the next tab (the one after the one removed).

                      Why?

                      M 1 Reply Last reply
                      0
                      • M Mark81

                        @J.Hilk said in Detach tabs from QTabWidget and restore them:

                        Removing a Widget and passing it to an other Layout is usually how one "moves" widgets around, yes :-)

                        Unfortunately I'm still doing it wrong. Let's see this short function:

                        void MainWindow::tabView_tabCloseRequested(int index)
                        {
                            QString name = ui->tabView->tabText(index); // retrieve the name of the tab
                            QLayout *layout = ui->tabView->widget(index)->layout(); // temporary save the pointer to the content
                            ui->tabView->tabBar()->removeTab(index); // remove the tab (now we have only the pointer above to its content)
                        
                            DialogPopup *widget = new DialogPopup(); // create a new Dialog
                            widget->setWindowTitle(name); // set the title like the name of the tab removed
                            widget->setLayout(layout); // place here the content of the tab removed
                            widget->show(); // show the dialog
                        }
                        

                        The dialog is created with the correct content, but the downside is it clears the content of the next tab (the one after the one removed).

                        Why?

                        M Offline
                        M Offline
                        Mark81
                        wrote on last edited by
                        #11

                        @Mark81 said in Detach tabs from QTabWidget and restore them:

                        ui->tabView->tabBar()->removeTab(index); // remove the tab (now we have only the pointer above to its content)
                        

                        Here the correct statement:

                        ui->tabView->removeTab(index); // remove the tab (now we have only the pointer above to its content)
                        
                        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