githubuser0xFFFF/Qt-Advanced-Docking-System

restoreState then add CDockWidget to a DockArea crash

gooker opened this issue · 7 comments

The following is the code that can reproduce the problem. A simple program starts restorestate, then clicks click in the menu to call the btn_click function, and the last line crashes I'm not sure if it's due to incorrect usage or a program bug

mainwindow.cpp

#include "../../examples/simple/MainWindow.h"

#include "ui_MainWindow.h"

#include <QLabel>
#include <QTimer>
#include <QSettings>
#include <QPlainTextEdit>


using namespace ads;
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    //menul click call btn
    connect(ui->actionclic, &QAction::triggered, this, &MainWindow::btn_click);

    //set a center dock
	m_DockManager = new ads::CDockManager(this);
    QPlainTextEdit* w = new QPlainTextEdit();
    CDockWidget* CenterDock = new CDockWidget("Show");
    CenterDock->setWidget(w);
    CenterDock->setFeature(ads::CDockWidget::NoTab, true);
    CenterDockArea = m_DockManager->setCentralWidget(CenterDock);

    restoreState();
}

void MainWindow::btn_click()
{
    CDockWidget* ImageDockWidget = new ads::CDockWidget("name");
    QLabel* label_time = new QLabel();
    label_time->setText("");
    ImageDockWidget->setWidget(label_time);

    // click crash this
    m_DockManager->addDockWidget(ads::CenterDockWidgetArea, ImageDockWidget,CenterDockArea);
}

void MainWindow::saveState()
{
    QSettings Settings("config.ini", QSettings::IniFormat);
    Settings.setValue("mainWindow/Geometry", this->saveGeometry());
    Settings.setValue("mainWindow/State", QMainWindow::saveState());
    Settings.setValue("mainWindow/DockingState", m_DockManager->saveState());
}

void MainWindow::restoreState()
{
    QSettings Settings("config.ini", QSettings::IniFormat);
    this->restoreGeometry(Settings.value("mainWindow/Geometry").toByteArray());
    QMainWindow::restoreState(Settings.value("mainWindow/State").toByteArray());
    m_DockManager->restoreState(Settings.value("mainWindow/DockingState").toByteArray());
}

MainWindow::~MainWindow()
{
    saveState();
    delete ui;
}


mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include "DockManager.h"

QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
    void saveState();
    void restoreState();
public slots:
    void btn_click();

private:
    Ui::MainWindow *ui;
    ads::CDockManager* m_DockManager;
    ads::CDockAreaWidget* CenterDockArea;
};

#endif // MAINWINDOW_H

Please check, if it works in the demo application. If it works there, then find out, what you are doing differently.

Please check, if it works in the demo application. If it works there, then find out, what you are doing differently.

demo restore ok, but demo dont have add CDockWidget to a CenterDockArea

What have you done so far to debug the problem?

What have you done so far to debug the problem?

I use demo , add a CenterDockArea ,and set a click like this
1712745251968

  1. start demo, close some dock,click "save state", close demo;
  2. start demo, add like before img a sample dock to centerdockarea, and then crash
1712745113669

@githubuser0xFFFF

I have found a simple verification method based on demo ,Not related to center dock

  1. Adjust demo/MainWindows. cpp TopDockArea to a non local variable, such as in struct MainWindows Private
    Internal definition
 ads:: CDockAreaWidget * TopDockArea;
  1. Adjust demo/MainWindow. cpp void MainWindow Private:: createContent()
auto TopDockArea=DockManager ->addDockWidget (ads:: TopDockWidgetArea, FileSystemWidget);

To

TopDockArea=DockManager ->addDockWidget (ads:: TopDockWidgetArea, FileSystemWidget);
  1. Find a slot function, such as void CMainWindow:: createEditor()
    Add code
    ads::CDockWidget* TestDockWidget = new ads::CDockWidget("test");
    QLabel* label_time = new QLabel();
    label_time->setText("");
    TestDockWidget->setWidget(label_time);
    d->DockManager->addDockWidget(ads::CenterDockWidgetArea, TestDockWidget,d->TopDockArea);
  1. After compiling and running, save/restore the state, and then click "Create Docked Editor"

After calling restoreState() the TopDockArea is not valid anymore. It holds a pointer to a dock area of the previous state. If you load another state, then all existing dock areas may me deleted because the restored state may have totally differnt dock areas.

After calling restoreState() the TopDockArea is not valid anymore. It holds a pointer to a dock area of the previous state. If you load another state, then all existing dock areas may me deleted because the restored state may have totally differnt dock areas.

thks