desktop: be smarter about filling splitters

On state change, the splitters were completely emptied and
refilled. Instead try to reuse already existing splitter
slots. This reduces annoying flickering.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
Berthold Stoeger 2021-01-27 22:06:41 +01:00 committed by Dirk Hohndel
parent c584e28f2e
commit aefbde93ce
2 changed files with 53 additions and 29 deletions

View file

@ -338,10 +338,21 @@ MainWindow::MainWindow() : QMainWindow(),
#endif #endif
} }
static void clearSplitter(QSplitter &splitter)
{
// Qt's ownership model is absolutely hare-brained.
// To remove a widget from a splitter, you reparent it, which
// informs the splitter via a signal. Wow.
while (splitter.count() > 0)
splitter.widget(0)->setParent(nullptr);
}
MainWindow::~MainWindow() MainWindow::~MainWindow()
{ {
// Remove widgets from the splitters so that they don't delete singletons. // Remove widgets from the splitters so that they don't delete singletons.
clearSplitters(); clearSplitter(*topSplitter);
clearSplitter(*bottomSplitter);
clearSplitter(*ui.mainSplitter);
write_hashes(); write_hashes();
m_Instance = nullptr; m_Instance = nullptr;
} }
@ -1575,29 +1586,27 @@ void MainWindow::registerApplicationState(ApplicationState state, Quadrants q)
applicationState[(int)state] = q; applicationState[(int)state] = q;
} }
void MainWindow::setQuadrantWidget(const Quadrant &q, QSplitter &splitter) void MainWindow::setQuadrantWidget(QSplitter &splitter, const Quadrant &q, int pos)
{ {
if (q.widget) { if (!q.widget)
return;
if (splitter.count() > pos)
splitter.replaceWidget(pos, q.widget);
else
splitter.addWidget(q.widget); splitter.addWidget(q.widget);
splitter.setCollapsible(splitter.count() - 1, false); splitter.setCollapsible(pos, false);
q.widget->setEnabled(!(q.flags & FLAG_DISABLED)); q.widget->setEnabled(!(q.flags & FLAG_DISABLED));
} }
}
static void clearSplitter(QSplitter &splitter) void MainWindow::setQuadrantWidgets(QSplitter &splitter, const Quadrant &left, const Quadrant &right)
{ {
// Qt's ownership model is absolutely hare-brained. int num = (left.widget != nullptr) + (right.widget != nullptr);
// To remove a widget from a splitter, you reparent it, which // Remove superfluous widgets by reparenting to null.
// informs the splitter via a signal. Wow. while (splitter.count() > num)
while (splitter.count() > 0) splitter.widget(splitter.count() - 1)->setParent(nullptr);
splitter.widget(0)->setParent(nullptr);
}
void MainWindow::clearSplitters() setQuadrantWidget(splitter, left, 0);
{ setQuadrantWidget(splitter, right, left.widget != nullptr ? 1 : 0);
clearSplitter(*topSplitter);
clearSplitter(*bottomSplitter);
clearSplitter(*ui.mainSplitter);
} }
bool MainWindow::userMayChangeAppState() const bool MainWindow::userMayChangeAppState() const
@ -1614,20 +1623,35 @@ void MainWindow::setApplicationState(ApplicationState state)
setAppState(state); setAppState(state);
clearSplitters(); clearSplitter(*topSplitter);
clearSplitter(*bottomSplitter);
const Quadrants &quadrants = applicationState[(int)state]; const Quadrants &quadrants = applicationState[(int)state];
setQuadrantWidget(quadrants.topLeft, *topSplitter); setQuadrantWidgets(*topSplitter, quadrants.topLeft, quadrants.topRight);
setQuadrantWidget(quadrants.topRight, *topSplitter); setQuadrantWidgets(*bottomSplitter, quadrants.bottomLeft, quadrants.bottomRight);
setQuadrantWidget(quadrants.bottomLeft, *bottomSplitter);
setQuadrantWidget(quadrants.bottomRight, *bottomSplitter);
if (topSplitter->count() >= 1) { if (topSplitter->count() >= 1) {
ui.mainSplitter->addWidget(topSplitter.get()); // Add topSplitter if it is not already shown
if (ui.mainSplitter->count() == 0 ||
ui.mainSplitter->widget(0) != topSplitter.get()) {
ui.mainSplitter->insertWidget(0, topSplitter.get());
ui.mainSplitter->setCollapsible(ui.mainSplitter->count() - 1, false); ui.mainSplitter->setCollapsible(ui.mainSplitter->count() - 1, false);
} }
} else {
// Remove topSplitter by reparenting it. So weird.
topSplitter->setParent(nullptr);
}
if (bottomSplitter->count() >= 1) { if (bottomSplitter->count() >= 1) {
// Add bottomSplitter if it is not already shown
if (ui.mainSplitter->count() == 0 ||
ui.mainSplitter->widget(ui.mainSplitter->count() - 1) != bottomSplitter.get()) {
ui.mainSplitter->addWidget(bottomSplitter.get()); ui.mainSplitter->addWidget(bottomSplitter.get());
ui.mainSplitter->setCollapsible(ui.mainSplitter->count() - 1, false); ui.mainSplitter->setCollapsible(ui.mainSplitter->count() - 1, false);
} }
} else {
// Remove bottomSplitter by reparenting it. So weird.
bottomSplitter->setParent(nullptr);
}
restoreSplitterSizes(); restoreSplitterSizes();

View file

@ -184,7 +184,6 @@ private:
void saveSplitterSizes(); void saveSplitterSizes();
void restoreSplitterSizes(); void restoreSplitterSizes();
void updateLastUsedDir(const QString &s); void updateLastUsedDir(const QString &s);
void clearSplitters();
bool filesAsArguments; bool filesAsArguments;
UpdateManager *updateManager; UpdateManager *updateManager;
std::unique_ptr<LocationInformationWidget> diveSiteEdit; std::unique_ptr<LocationInformationWidget> diveSiteEdit;
@ -220,7 +219,8 @@ private:
Quadrants applicationState[(size_t)ApplicationState::Count]; Quadrants applicationState[(size_t)ApplicationState::Count];
static void addWidgets(const Quadrant &); static void addWidgets(const Quadrant &);
bool userMayChangeAppState() const; bool userMayChangeAppState() const;
void setQuadrantWidget(const Quadrant &q, QSplitter &splitter); void setQuadrantWidget(QSplitter &splitter, const Quadrant &q, int pos);
void setQuadrantWidgets(QSplitter &splitter, const Quadrant &left, const Quadrant &right);
void registerApplicationState(ApplicationState state, Quadrants q); void registerApplicationState(ApplicationState state, Quadrants q);
QMenu *connections; QMenu *connections;