I have a custom class in which I create a QFrame
, with a QGrid Layout
, that has a QMainWindow
which has a QDockWidget
which owns an OpenGLWidget
. Now that I have all of that out of the way I can show you what it is like to create the class.
std::unique_ptr<QFrame, std::default_delete<QFrame>> MyProgram::createNewRenderWindow(bool hasFeatures)
{
QGridLayout *baseLayout = new QGridLayout();
auto newBaseFrame = std::make_unique<QFrame>(new QFrame);
auto newRenderView = std::make_unique<RenderView>(hasFeatures);
newBaseFrame->setFrameStyle(QFrame::StyledPanel);
newBaseFrame->setFrameShadow(QFrame::Sunken);
baseLayout->addWidget(newRenderView.release());
newBaseFrame->setLayout(baseLayout);
return newBaseFrame;
}
The class RenderView is the class that has a QMainWindow
with a QDockWidget
that owns an OpenGLWidget
. I then set that in a QFrame
with a QGridLayout
. Once that is returned, I set it in my gui by calling the following in my constructor:
auto mainRenderView = createNewRenderWindow(false);
ui->splitter->addWidget(mainRenderView.release());
The reason, in this case, that I pass false is because my main render view should have no features enabled in it's dock widget. So I set this one to false because it is my main render window. When I create a new render view, I set this argument to true so that I have all the features of a dock widget.
In my program, I have created a way to create more than one render view, essentially, the ability to split the render view into 4 different windows. However, the main render view is always the same. So if the user wants to add two more windows they can. I do this with the following:
std::unique_ptr<QSplitter, std::default_delete<QSplitter>> MyProgram::createNewSplitter(Qt::Orientation orientation)
{
auto newSplitter = std::make_unique<QSplitter>(new QSplitter);
auto newTopWindow = createNewRenderWindow(true);
auto newBottomWindow = createNewRenderWindow(true);
newSplitter->setOrientation(orientation);
newSplitter->addWidget(newTopWindow.release());
newSplitter->addWidget(newBottomWindow.release());
newSplitter->setSizes(QList<int>({HALFRENDERVIEWSIZE, HALFRENDERVIEWSIZE}));
return newSplitter;
}
And then I add it to the splitter like this:
auto newWindows = createNewSplitter(Qt::Vertical);
ui->splitter->setOrientation(Qt::Horizontal);
ui->splitter->addWidget(newWindows.release());
ui->splitter->setSizes(QList<int>({HALFRENDERVIEWSIZE, HALFRENDERVIEWSIZE}));
This will split the main view in half, and then add two render windows on the right hand side in another QSplitter
. Okay, now that I have explain all of that (hopefully well enough, the program is huge and I don't know how to create a minimal example of this). I can explain the real problem.
I can go from one render view, to two, or to three, or to four if I want to. I can go from four to three or two. However, I cannot go from four to one, three to one, or two to one. And this is a problem with the Copy Constructor as stated in the post I just linked. My first idea, was to extract the main render window from the ui->splitter
, assign it to a new object, erase all of the children, and place the extracted main window back into the ui->splitter
. However, trying that I quickly learned that once I delete the children from the ui->splitter
, I delete the children from the extracted main window.
void MyProgram::on_actionOne_View_triggered()
{
auto mainRenderView = std::move(ui->splitter->widget(MAINRENDERINDEX));
std::cout << mainRenderView.children().count() << " extracted children" << std::endl;
std::cout << ui->splitter->children().count() << std::endl;
qDeleteAll(ui->splitter->findChildren<QSplitter*>());
std::cout << ui->splitter->children().count() << std::endl;
qDeleteAll(ui->splitter->findChildren<QFrame*>());
std::cout << ui->splitter->children().count() <<std::endl;
std::cout << mainRenderView.children().count() << " extracted children" << std::endl;
ui->splitter->addWidget(mainRenderView.release());
}
The first print statement will print out 2, which tells me that I have successfully extracted the widget that I wanted. I then print out the total number of children that ui->splitter
has. Which tells me it has 4 children. I then delete all of the QSplitters
and print out the number, which leaves the QFrames
, that reports there are two QFrames
left. I then delete the QFrames
and it reports back 0 children left in the ui->splitter
. However, I then print out the children mainRenderView
has and it reports back 0. Then it tries to insert the extracted widget into the ui->splitter
and crashes the program since there is nothing to insert.
What is the best way to do this? I have toyed with the idea of creating my own copy method, however I have read you just don't do that. Is there anyway to delete all of the children and go back to the starting state that the program launches in?