refactor: DockWidget::isOpen() now keeps its state in the controller

No longer tied to QtWidget visibility. This will make it easier to
make new frontends.
This commit is contained in:
Sergio Martins
2022-08-27 13:27:18 +01:00
parent ea7cb3cbbb
commit 764385de9f
9 changed files with 60 additions and 16 deletions

View File

@@ -58,8 +58,11 @@ void Controller::setVisible(bool is)
{
if (m_view)
m_view->setVisible(is);
else
qWarning() << Q_FUNC_INFO << "No view";
if (m_isVisible == is)
return;
Q_EMIT visibleChanged(is);
}
QRect Controller::rect() const

View File

@@ -92,6 +92,9 @@ Q_SIGNALS:
///@brief signal counterpart for setParentView()
void parentViewChanged(View *parent);
///@brief signal counterpart for setVisible()
void visibleChanged(bool);
protected:
virtual void setParentView_impl(View *parent);
@@ -99,6 +102,7 @@ private:
void setParent(QObject *) = delete;
View *m_view = nullptr;
bool m_inDtor = false;
bool m_isVisible = true;
const Type m_type;
};

View File

@@ -402,7 +402,7 @@ Controllers::TitleBar *DockWidget::titleBar() const
bool DockWidget::isOpen() const
{
return d->toggleAction->isChecked();
return d->m_isOpen;
}
QStringList DockWidget::affinities() const
@@ -418,6 +418,7 @@ void DockWidget::show()
// This reduces flickering on some platforms
d->morphIntoFloatingWindow();
} else {
d->setIsOpen(true);
view()->show();
}
}
@@ -582,6 +583,7 @@ Controllers::FloatingWindow *DockWidget::Private::morphIntoFloatingWindow()
Layouting::AtomicSanityChecks checks(floatingWindow->dropArea()->rootItem());
floatingWindow->view()->show();
setIsOpen(true);
return floatingWindow;
} else {
@@ -702,6 +704,7 @@ void DockWidget::Private::toggle(bool enabled)
{
if (Controllers::SideBar *sb = sideBar()) {
// The widget is in the sidebar, let's toggle its overlayed state
QScopedValueRollback<bool> guard(m_removingFromOverlay, true);
sb->toggleOverlay(q);
} else {
// The most common case. The dock widget is not in the sidebar. just close or open it.
@@ -727,7 +730,7 @@ void DockWidget::Private::updateToggleAction()
void DockWidget::Private::updateFloatAction()
{
if (m_willUpdateActions)
if (m_willUpdateActions || m_removingFromOverlay)
return;
QScopedValueRollback<bool> recursionGuard(m_updatingFloatAction,
@@ -758,6 +761,10 @@ void DockWidget::Private::onDockWidgetHidden()
void DockWidget::Private::close()
{
if (m_inClose)
return;
QScopedValueRollback<bool> guard(m_inClose, true);
if (!m_processingToggleAction && !q->isOpen()) {
q->setParentView(nullptr);
return;
@@ -766,6 +773,8 @@ void DockWidget::Private::close()
if (m_isPersistentCentralDockWidget)
return;
setIsOpen(false);
// If it's overlayed and we're closing, we need to close the overlay
if (Controllers::SideBar *sb = DockRegistry::self()->sideBarForDockWidget(q)) {
auto mainWindow = sb->mainWindow();
@@ -1060,3 +1069,16 @@ void DockWidget::Private::onCloseEvent(QCloseEvent *e)
if (e->isAccepted())
close();
}
void DockWidget::Private::setIsOpen(bool is)
{
if (is == m_isOpen || m_inOpenSetter)
return;
QScopedValueRollback<bool> guard(m_inOpenSetter, true);
if (!is)
close();
m_isOpen = is;
}

View File

@@ -277,7 +277,7 @@ public:
/**
* @brief Returns whether this dock widget is open.
* Equivalent to calling toggleAction().isChecked() or isVisible()
* Equivalent to calling toggleAction().isChecked()
*/
bool isOpen() const;

View File

@@ -179,6 +179,8 @@ public:
/// widget This goes up the hierarchy, while mdiDropAreaWrapper goes down.
DockWidget *mdiDockWidgetWrapper() const;
void setIsOpen(bool);
const QString name;
QStringList affinities;
QString title;
@@ -199,6 +201,10 @@ public:
bool m_isMovingToSideBar = false;
bool m_isSettingCurrent =
false; // TODOm4: Remove once DockWidget::onShown() doesn't drive things
bool m_isOpen = false;
bool m_inOpenSetter = false;
bool m_inClose = false;
bool m_removingFromOverlay = false; // TODOm4: Remove soon
QSize m_lastOverlayedSize = QSize(0, 0);
int m_userType = 0;
bool m_willUpdateActions = false;

View File

@@ -258,7 +258,7 @@ void Group::insertWidget(DockWidget *dockWidget, int index, InitialOption adding
insertDockWidget(dockWidget, index);
if (addingOption.startsHidden()) {
dockWidget->view()->close(); // Ensure closed
dockWidget->view()->close(); // Ensure closed. TODOm4: Call controller instead.
} else {
if (hasSingleDockWidget()) {
setObjectName(dockWidget->uniqueName());
@@ -272,6 +272,8 @@ void Group::insertWidget(DockWidget *dockWidget, int index, InitialOption adding
} else if (addingOption.preservesCurrentTab() && originalCurrentIndex != -1) {
setCurrentTabIndex(originalCurrentIndex);
}
dockWidget->d->setIsOpen(true);
}
connect(dockWidget, &DockWidget::titleChanged, this, &Group::onDockWidgetTitleChanged);

View File

@@ -616,28 +616,32 @@ void MainWindow::clearSideBarOverlay(bool deleteFrame)
if (!d->m_overlayedDockWidget)
return;
Controllers::Group *group = d->m_overlayedDockWidget->d->group();
auto overlayedDockWidget = d->m_overlayedDockWidget;
d->m_overlayedDockWidget = nullptr;
Controllers::Group *group = overlayedDockWidget->d->group();
if (!group) { // prophylactic check
d->m_overlayedDockWidget = nullptr;
return;
}
const SideBarLocation loc = d->m_overlayedDockWidget->sideBarLocation();
d->m_overlayedDockWidget->d->lastPosition()->setLastOverlayedGeometry(loc, group->geometry());
const SideBarLocation loc = overlayedDockWidget->sideBarLocation();
overlayedDockWidget->d->lastPosition()->setLastOverlayedGeometry(loc, group->geometry());
group->unoverlay();
if (deleteFrame) {
d->m_overlayedDockWidget->QObject::setParent(nullptr);
d->m_overlayedDockWidget->setParentView(nullptr);
Q_EMIT d->m_overlayedDockWidget->isOverlayedChanged(false);
d->m_overlayedDockWidget = nullptr;
overlayedDockWidget->QObject::setParent(nullptr);
overlayedDockWidget->d->m_removingFromOverlay = true; // TODOm4: Remove soon
overlayedDockWidget->setParentView(nullptr);
overlayedDockWidget->d->m_removingFromOverlay = false;
Q_EMIT overlayedDockWidget->isOverlayedChanged(false);
overlayedDockWidget = nullptr;
delete group;
} else {
// No cleanup, just unset. When we drag the overlay it becomes a normal floating window
// meaning we reuse Frame. Don't delete it.
Q_EMIT d->m_overlayedDockWidget->isOverlayedChanged(false);
d->m_overlayedDockWidget = nullptr;
Q_EMIT overlayedDockWidget->isOverlayedChanged(false);
overlayedDockWidget = nullptr;
}
}

View File

@@ -77,7 +77,9 @@ TEST_CASE("isOpen")
CHECK(dw->isOpen());
CHECK(dw->isFloating());
auto dw2 = Config::self().viewFactory()->createDockWidget("dw2")->asDockWidgetController();
CHECK(dw->isCurrentTab());
dw->addDockWidgetAsTab(dw2);
CHECK(dw2->isOpen());
dw2->setAsCurrentTab();
CHECK(!dw->isCurrentTab());
CHECK(dw2->isCurrentTab());

View File

@@ -819,6 +819,7 @@ void TestQtWidgets::tst_sidebarOverlayGetsHiddenOnClick()
Tests::clickOn(dw2->mapToGlobal(dw2->rect().bottomLeft() + QPoint(5, -5)), dw2->view());
QVERIFY(!dw1->isOverlayed());
QVERIFY(dw1->isInSideBar());
auto widget2 = Platform::instance()->tests_createView({ true });
dw2->setGuestView(widget2->asWrapper());