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. tabifyDockWidget() adding unknown widgets

tabifyDockWidget() adding unknown widgets

Scheduled Pinned Locked Moved Unsolved General and Desktop
13 Posts 2 Posters 1.5k 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.
  • J Offline
    J Offline
    Julieng
    wrote on 30 Dec 2019, 20:43 last edited by Julieng
    #1

    Hello,

    I am fighting against an issue for several days without understanding the issue. Even if I delete QDockWidgets, the number of widgets is always increasing. Could you help me ? Thanks in advance !

    I have a vector of Qt panels stored in a vector:

    myWindow {
    public:
    	void rebuildContent();
    
    private:
    	std::vector<uncloseableDockWidget *> m_widgets;
    }
    

    uncloseableDockWidget is an interface impeding QDockWidgets to be closed.

    class uncloseableDockWidget : public QDockWidget {
        Q_OBJECT
    
    public:
        explicit uncloseableDockWidget(const QString & title, QWidget * parent = nullptr, Qt::WindowFlags flags = Qt::WindowFlags()) : QDockWidget(title, parent, flags) {
            setFeatures(QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable);
            setAllowedAreas(Qt::AllDockWidgetAreas);
        }
    
        virtual ~uncloseableDockWidget() override {
        }
    
    public slots:
        virtual void updateView() = 0;
    
    protected:
        void closeEvent(QCloseEvent * event) override {
    	event->ignore();
        }
    };
    

    Now, coming back to my main window, when calling rebuildContent, I clear the QDockWidgets and build new ones:

    void myWindow::rebuildContent() {
        std::cout << "test1 " << QApplication::allWidgets().size() << std::endl;
        // Remove already existing dock widgets
        for(uncloseableDockWidget * w:m_widgets) {
            m_container->removeDockWidget(w);
            delete w;
        }
        m_widgets.clear();
        std::cout << "test2 " << QApplication::allWidgets().size() << std::endl;
        // Add new widgets
        m_widgets.emplace_back(new customDockWidget(tr("widget1")));
        m_widgets.emplace_back(new customDockWidget(tr("widget2")));
        // Connect signals
        std::cout << "test3 " << QApplication::allWidgets().size() << std::endl;
        for(uncloseableDockWidget * w:m_widgets)
            connect(w, SIGNAL(updateViewRequest()), this, SLOT(updateView()));
        std::cout << "test4 " << QApplication::allWidgets().size() << std::endl;
        // Add and tabify dock widgets
        for(uncloseableDockWidget * w:m_widgets)
            m_container->addDockWidget(Qt::RightDockWidgetArea, w);
        std::cout << "test5 " << QApplication::allWidgets().size() << std::endl;
        for(unsigned int i=1; i<m_widgets.size(); i++)
            m_container->tabifyDockWidget(m_widgets[i-1], m_widgets[i]);
        std::cout << "test6 " << QApplication::allWidgets().size() << std::endl;
        if(m_listOfDockWidgets.size())
            m_widgets.front()->raise();
        std::cout << "test7 " << QApplication::allWidgets().size() << std::endl;
    }
    

    When I run function 'rebuildContent' twice, here is the result:

    test1 305
    test2 305 -> no widget in m_widgets for first call 
    test3 365 -> build 60 widgets
    test4 365 -> nothing done (just connecting things)
    test5 365 -> nothing done (adding QDockWidgets)
    test6 368 -> I do not understand why 3 widgets are created when tabifying
    test7 368 -> nothing done (just raising tab)
    ---
    test1 368 -> same amount as before
    test2 308 -> removing the 60 widgets however, the 3 widgets built due to tabifying remains
    test3 368 -> build 60 widgets
    test4 368
    test5 368
    test6 371 -> 3 new widgets due to tabifying...
    test7 371
    

    Is there a reason to get these 3 additional widgets and why the removeDockWidget does not delete it automatically ?

    1 Reply Last reply
    0
    • S Offline
      S Offline
      SGaist
      Lifetime Qt Champion
      wrote on 30 Dec 2019, 21:36 last edited by
      #2

      Hi,

      You are building objects that are customWidget are you putting anything in there that is parented differently ?

      Without seing the whole code it's difficult to determine what might be happening.

      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
      0
      • J Offline
        J Offline
        Julieng
        wrote on 31 Dec 2019, 06:23 last edited by
        #3

        Hello SGaist, when I comment the "tabifyDockWidget" line, I do not have any issue.

        Code inside the customWidgets is quite simple.

        An example:

            QWidget * widget = new QWidget();
            setWidget(widget);
            QVBoxLayout * layout = new QVBoxLayout();
            widget->setLayout(layout);
             m_map = new baseItemMap(); // With m_map beeing a QCustomPlot figure
             layout->addWidget(m_map);
        

        Another example:

            QScrollArea * scroll = new QScrollArea();
            setWidget(scroll);
            scroll->setBackgroundRole(QPalette::Light);
            scroll->setFrameShape(QFrame::NoFrame);
            scroll->setWidgetResizable(true);
            QWidget * widget = new QWidget();
            scroll->setWidget(widget);
            QVBoxLayout * layout = new QVBoxLayout();
            widget->setLayout(layout);
        
            QLabel * labTX = new QLabel(tr("<b>Text</b>"));
            layout->addWidget(labTX);
        
            m_table = new customTableView(); // Derived from a QTableView
            layout->addWidget(m_table);
        
        1 Reply Last reply
        0
        • J Offline
          J Offline
          Julieng
          wrote on 31 Dec 2019, 06:57 last edited by
          #4

          I've just tried with empty customWidget and I continue to "leak" widgets.

          1 Reply Last reply
          0
          • S Offline
            S Offline
            SGaist
            Lifetime Qt Champion
            wrote on 31 Dec 2019, 07:32 last edited by
            #5

            I just realized, when you call tabify, there's a QTabWidget that is created and tabs added for each widget you put together.

            There you have the three widgets.

            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
            0
            • J Offline
              J Offline
              Julieng
              wrote on 31 Dec 2019, 14:18 last edited by
              #6

              Thanks SGaist, that's an interesting point ! So, how could I remove these QTabWidgets ? Do I have to do it before or after the following piece of code ?

               for(uncloseableDockWidget * w:m_widgets) {
                    m_container->removeDockWidget(w);
                    delete w;
              }
              m_widgets.clear();
              
              1 Reply Last reply
              0
              • J Offline
                J Offline
                Julieng
                wrote on 1 Jan 2020, 17:12 last edited by
                #7

                I tried to remove the central widget like this :

                delete m_container->centralWidget();
                

                and build a new one. I thought that these additional widgets would be "parented" to the central widget. However, it does not work. Any idea to delete it ?

                1 Reply Last reply
                0
                • S Offline
                  S Offline
                  SGaist
                  Lifetime Qt Champion
                  wrote on 1 Jan 2020, 19:48 last edited by
                  #8

                  Well, I think you have found an edge case. From the quick look I did to the sources of QMainWindow and its internal classes, the fact that you are deleting the dock widget every time seems to not be handled in the "tabification" part (I have to take a deeper dive to ensure that).

                  I must say that it's pretty unusual to completely destroy dock widgets and recreate them like you are currently doing.

                  Would you mind providing a minimal compilable example to reproduce that ?

                  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
                  2
                  • J Offline
                    J Offline
                    Julieng
                    wrote on 2 Jan 2020, 10:58 last edited by
                    #9

                    Thanks SGaist, here is a complete exemple :

                    main.cpp:

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

                    mainwindow.h

                    #ifndef MAINWINDOW_H
                    #define MAINWINDOW_H
                    
                    #include <iostream>
                    #include <QMainWindow>
                    #include <QDockWidget>
                    #include <QCloseEvent>
                    #include <QLabel>
                    #include <QPushButton>
                    #include <QBoxLayout>
                    #include <QApplication>
                    
                    class uncloseableDockWidget : public QDockWidget {
                        Q_OBJECT
                    
                    public:
                        /**
                         * @brief Constructor
                         * @param title: title
                         * @param parent: parent widget
                         * @param flags: flags
                         */
                        explicit uncloseableDockWidget(const QString & title, QWidget * parent = nullptr, Qt::WindowFlags flags = Qt::WindowFlags()) : QDockWidget(title, parent, flags) {
                            setFeatures(QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable);
                            setAllowedAreas(Qt::AllDockWidgetAreas);
                        }
                    
                        /**
                         * @brief Destructor
                         */
                        virtual ~uncloseableDockWidget() override {}
                    
                    public slots:
                        /**
                         * @brief Update view
                         */
                        virtual void updateView() = 0;
                    
                    protected:
                        /**
                         * @brief Close event
                         * @param event: event
                         */
                        void closeEvent(QCloseEvent * event) override {
                            event->ignore();
                        }
                    };
                    
                    class dock : public uncloseableDockWidget {
                        Q_OBJECT
                    
                    public:
                        dock(const QString & title, QWidget * parent = nullptr, Qt::WindowFlags flags = Qt::WindowFlags()) : uncloseableDockWidget(title, parent, flags) {}
                    
                        void updateView() override {}
                    };
                    
                    class tab1 : public QWidget {
                        Q_OBJECT
                    
                    public:
                        tab1(QWidget * parent = nullptr) : QWidget(parent) {
                            QVBoxLayout * layout = new QVBoxLayout();
                            setLayout(layout);
                            QPushButton * bt = new QPushButton("test");
                            layout->addWidget(bt);
                            connect(bt, SIGNAL(clicked()), this, SIGNAL(btClicked()));
                        }
                    
                    signals:
                        void btClicked();
                    };
                    
                    class tab2 : public QWidget {
                        Q_OBJECT
                    
                    public:
                        tab2(QWidget * parent = nullptr) : QWidget(parent) {
                            QVBoxLayout * layout = new QVBoxLayout();
                            setLayout(layout);
                            m_content = new QMainWindow();
                            layout->addWidget(m_content);
                            m_content->setCentralWidget(new QLabel("test"));
                        }
                    
                    public slots:
                        void update() {
                            std::cout << "test1: " << QApplication::allWidgets().size() << std::endl;
                            // Remove already existing dock widgets
                            for(uncloseableDockWidget * w:m_docks) {
                                m_content->removeDockWidget(w);
                                delete w;
                            }
                            m_docks.clear();
                            std::cout << "test2: " << QApplication::allWidgets().size() << std::endl;
                            // Add new dock widgets
                            m_docks.emplace_back(new dock("title1"));
                            m_docks.emplace_back(new dock("title2"));
                            m_docks.emplace_back(new dock("title3"));
                            std::cout << "test3: " << QApplication::allWidgets().size() << std::endl;
                            // Add and tabify dock widgets
                            for(uncloseableDockWidget * w:m_docks)
                                m_content->addDockWidget(Qt::RightDockWidgetArea, w);
                            std::cout << "test4: " << QApplication::allWidgets().size() << std::endl;
                            for(unsigned int i=1; i<m_docks.size(); i++)
                                m_content->tabifyDockWidget(m_docks[i-1], m_docks[i]);
                            std::cout << "test5: " << QApplication::allWidgets().size() << std::endl;
                            if(m_docks.size())
                                m_docks.front()->raise();
                            std::cout << "test6: " << QApplication::allWidgets().size() << std::endl;
                        }
                    
                    private:
                        QMainWindow * m_content = nullptr;
                        std::vector<uncloseableDockWidget *> m_docks;
                    };
                    
                    class MainWindow : public QMainWindow
                    {
                        Q_OBJECT
                    
                    public:
                        MainWindow(QWidget * /*parent*/ = nullptr) {
                            m_tab = new QTabWidget();
                            setCentralWidget(m_tab);
                            tab1 * t1 = new tab1();
                            m_tab->addTab(t1, "t1");
                            tab2 * t2 = new tab2();
                            m_tab->addTab(t2, "t2");
                            connect(t1, SIGNAL(btClicked()), t2, SLOT(update()));
                        }
                    
                        ~MainWindow() {
                    
                        }
                    private:
                        QTabWidget * m_tab = nullptr;
                    };
                    
                    #endif // MAINWINDOW_H
                    

                    Clicking various times on the "test" button in tab 1, you can see that number of widgets increases.

                    1 Reply Last reply
                    1
                    • J Offline
                      J Offline
                      Julieng
                      wrote on 10 Jan 2020, 19:29 last edited by
                      #10

                      Hello SGaist, is the example I provided enough to understand my issue ? Do you think I could get a workaround in order to avoid "leaking" widgets ? Thnanks in advance.

                      1 Reply Last reply
                      0
                      • S Offline
                        S Offline
                        SGaist
                        Lifetime Qt Champion
                        wrote on 11 Jan 2020, 16:35 last edited by
                        #11

                        So it looks like I never submitted my answer, sorry !

                        I took a look at the internals of QMainWindow and the handling of the QDockWidget "tabification" is more involved than what I thought.

                        There's no easy workaround per se but there's something I though about: do you really need to delete these dock widgets all the time ? Would a reset of their content be enough ? If you really need to delete them, what about just replacing the widget they contain ? Doing so, you would only have a set of QDockWidget and thus avoid the issue you are currently having.

                        In any case, I think it would be worth checking the bug report system to see if there's something related and if not, please open a repot providing your small code sample (including the corresponding pro file).

                        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
                        0
                        • J Offline
                          J Offline
                          Julieng
                          wrote on 12 Jan 2020, 20:06 last edited by
                          #12

                          Thanks SGaist for you answers ! I can change the way I manage the dock widgets (I could just clear the QMainWindow which contains these docks even if I think it will not be as elegant as my first solution). I'll open a bug report as you propose.

                          1 Reply Last reply
                          0
                          • S Offline
                            S Offline
                            SGaist
                            Lifetime Qt Champion
                            wrote on 12 Jan 2020, 20:19 last edited by
                            #13

                            I was rather thinking about cleaning the widgets within the dock widgets. So you keep the number of QDockWidgets constant.

                            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
                            0

                            • Login

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