/* This file is part of KDDockWidgets. SPDX-FileCopyrightText: 2019 Klarälvdalens Datakonsult AB, a KDAB Group company Author: Sérgio Martins SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only Contact KDAB at for commercial licensing options. */ #include "DockWidget.h" #include "core/DockWidget_p.h" #include "ViewWrapper_p.h" #include #include #include /** * @file * @brief Represents a dock widget. * * @author Sérgio Martins \ */ using namespace KDDockWidgets; using namespace KDDockWidgets::QtWidgets; class DockWidget::Private { public: explicit Private(DockWidget *q) : layout(new QVBoxLayout(q)) { layout->setSpacing(0); layout->setContentsMargins(0, 0, 0, 0); // propagate the max-size constraints from the guest widget to the DockWidget layout->setSizeConstraint(QLayout::SetMinAndMaxSize); } QVBoxLayout *const layout; KDBindings::ScopedConnection optionsChangedConnection; KDBindings::ScopedConnection guestViewChangedConnection; KDBindings::ScopedConnection isFocusedChangedConnection; KDBindings::ScopedConnection isFloatingChangedConnection; KDBindings::ScopedConnection isOpenChangedConnection; KDBindings::ScopedConnection windowActiveAboutToChangeConnection; KDBindings::ScopedConnection guestChangeConnection; KDBindings::ScopedConnection isCurrentTabConnection; }; DockWidget::DockWidget(const QString &uniqueName, DockWidgetOptions options, LayoutSaverOptions layoutSaverOptions, Qt::WindowFlags windowFlags) : View(new Core::DockWidget(this, uniqueName, options, layoutSaverOptions), Core::ViewType::DockWidget, nullptr, windowFlags) , Core::DockWidgetViewInterface(asDockWidgetController()) , d(new Private(this)) { d->guestChangeConnection = m_dockWidget->d->guestViewChanged.connect([this] { if (auto guest = widget()) { QWidget::setSizePolicy(guest->sizePolicy()); d->layout->addWidget(guest); } }); d->optionsChangedConnection = m_dockWidget->d->optionsChanged.connect([this](KDDockWidgets::DockWidgetOptions opts) { Q_EMIT optionsChanged(opts); }); d->guestViewChangedConnection = m_dockWidget->d->guestViewChanged.connect([this] { Q_EMIT guestViewChanged(); }); d->isFocusedChangedConnection = m_dockWidget->d->isFocusedChanged.connect([this](bool focused) { Q_EMIT isFocusedChanged(focused); }); d->isFloatingChangedConnection = m_dockWidget->d->isFloatingChanged.connect([this](bool floating) { Q_EMIT isFloatingChanged(floating); }); d->isOpenChangedConnection = m_dockWidget->d->isOpenChanged.connect([this](bool open) { Q_EMIT isOpenChanged(open); }); d->windowActiveAboutToChangeConnection = m_dockWidget->d->windowActiveAboutToChange.connect([this](bool active) { Q_EMIT windowActiveAboutToChange(active); }); d->isCurrentTabConnection = m_dockWidget->d->isCurrentTabChanged.connect([this](bool isCurrent) { Q_EMIT isCurrentTabChanged(isCurrent); }); m_dockWidget->init(); } DockWidget::~DockWidget() { delete d; } void DockWidget::setWidget(QWidget *widget) { m_dockWidget->setGuestView(ViewWrapper::create(widget)); } bool DockWidget::event(QEvent *e) { if (e->type() == QEvent::Show) m_dockWidget->open(); // NOLINTNEXTLINE(bugprone-parent-virtual-call) return QtWidgets::View::event(e); } void DockWidget::resizeEvent(QResizeEvent *e) { m_dockWidget->onResize(e->size()); // NOLINTNEXTLINE(bugprone-parent-virtual-call) QWidget::resizeEvent(e); } QWidget *DockWidget::widget() const { if (auto guest = m_dockWidget->guestView()) return View_qt::asQWidget(guest.get()); return nullptr; } QAction *DockWidget::toggleAction() const { return dynamic_cast(m_dockWidget->toggleAction()); } QAction *DockWidget::floatAction() const { return dynamic_cast(m_dockWidget->floatAction()); } std::shared_ptr DockWidget::focusCandidate() const { // For QtWidgets, if we focus the dock widget, we actually focus the user/guest widget // For QtQuick, the dock widget itself is a QtQuick FocusScope, so focus that instead. QtQuick will then focus the right inner // widget. return m_dockWidget->guestView(); } void DockWidget::mouseDoubleClickEvent(QMouseEvent *ev) { // The guest widget didn't want it, so block it now. // Otherwise it goes to the QTabWidget and it will make the window float. ev->accept(); }