diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ae13c7ba..bdf3bacc 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -210,6 +210,8 @@ set(KDDW_QTQUICK_FRONTEND_SRCS qtquick/TestHelpers_qtquick.cpp qtquick/LayoutSaverInstantiator.cpp qtquick/LayoutSaverInstantiator.h + # qtquick/views/DockWidget_qtquick.cpp + # qtquick/views/DockWidget_qtquick.h qtquick/views/Frame_qtquick.cpp qtquick/views/Frame_qtquick.h qtquick/views/View_qtquick.cpp diff --git a/src/qtquick/views/DockWidget_qtquick.cpp b/src/qtquick/views/DockWidget_qtquick.cpp index 7e4b410a..1e1f8705 100644 --- a/src/qtquick/views/DockWidget_qtquick.cpp +++ b/src/qtquick/views/DockWidget_qtquick.cpp @@ -10,9 +10,15 @@ */ #include "DockWidget_qtquick.h" +#include "FrameworkWidgetFactory.h" +#include "controllers/TitleBar.h" +#include "controllers/DockWidget.h" +#include "controllers/Frame.h" + +#include +#include #include -#include /** * @file @@ -22,32 +28,34 @@ */ using namespace KDDockWidgets; -using namespace KDDockWidgets::Controllers; using namespace KDDockWidgets::Views; class DockWidget_qtquick::Private { public: - Private(DockWidget_qtquick *q, Controllers::DockWidget *controller) - : layout(new QVBoxLayout(q)) - , m_controller(controller) + Private(DockWidget_qtquick *view, QQmlEngine *qmlengine) + : q(view->m_controller) + , m_visualItem(q->createItem(qmlengine, + Config::self().frameworkWidgetFactory()->dockwidgetFilename().toString())) + , m_qmlEngine(qmlengine) { - 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); + Q_ASSERT(m_visualItem); + m_visualItem->setParent(view); + m_visualItem->setParentItem(view); } - QVBoxLayout *const layout; - Controllers::DockWidget *const m_controller; + Controllers::DockWidget *const q; + QQuickItem *const m_visualItem; + QQmlEngine *const m_qmlEngine; }; DockWidget_qtquick::DockWidget_qtquick(Controllers::DockWidget *controller, - Qt::WindowFlags windowFlags) - : View_qtquick(controller, Type::DockWidget, nullptr, windowFlags) - , d(new Private(this, controller)) + Qt::WindowFlags windowFlags, QQmlEngine *engine) + : View_qtquick(controller, Type::DockWidget, nullptr, windowFlags) + , d(new Private(this, engine ? engine : Config::self().qmlEngine())) { + // To mimic what QtWidgets does when creating a new QWidget. + setVisible(false); } DockWidget_qtquick::~DockWidget_qtquick() @@ -55,38 +63,105 @@ DockWidget_qtquick::~DockWidget_qtquick() delete d; } -void DockWidget_qtquick::init() +void DockWidget_qtquick::setWidget(const QString &qmlFilename) { - connect(d->m_controller, &DockWidgetBase::widgetChanged, this, [this](QWidget *w) { - d->layout->addWidget(w); - }); + QQuickItem *guest = createItem(d->m_qmlEngine, qmlFilename); + if (!guest) + return; + + setWidget(guest); } -Controllers::DockWidget *DockWidget_qtquick::dockWidget() const +void DockWidget_qtquick::setWidget(QWidgetAdapter *widget) { - return d->m_controller; + widget->QWidgetAdapter::setParent(this); + makeItemFillParent(widget); + DockWidget::setWidget(widget); +} + +void DockWidget_qtquick::setWidget(QQuickItem *guest) +{ + auto adapter = new View_qtquick(nullptr, Type::None, this); + adapter->setIsWrapper(); + + // In case the user app needs to use them: + adapter->setProperty("originalParent", QVariant::fromValue(guest->parent())); + adapter->setProperty("originalParentItem", QVariant::fromValue(guest->parentItem())); + + guest->setParentItem(adapter); + guest->setParent(adapter); + makeItemFillParent(guest); + + setWidget(adapter); } bool DockWidget_qtquick::event(QEvent *e) { if (e->type() == QEvent::ParentChange) { - d->m_controller->onParentChanged(); + d->q->onParentChanged(); + Q_EMIT d->q->actualTitleBarChanged(); } else if (e->type() == QEvent::Show) { - d->m_controller->onShown(e->spontaneous()); + d->q->onShown(e->spontaneous()); } else if (e->type() == QEvent::Hide) { - d->m_controller->onHidden(e->spontaneous()); + d->q->onHidden(e->spontaneous()); + } else if (e->type() == QEvent::Close) { + d->q->onCloseEvent(static_cast(e)); } - return QWidget::event(e); + return DockWidget_qtquick::event(e); } -void DockWidget_qtquick::closeEvent(QCloseEvent *e) +QSize DockWidget_qtquick::minSize() const { - d->m_controller->onCloseEvent(e); + if (auto guestWidget = widget()) { + // The guests min-size is the same as the widget's, there's no spacing or margins. + return guestWidget->minimumSize(); + } + + return View_qtquick::minSize(); } -void DockWidget_qtquick::resizeEvent(QResizeEvent *e) +QSize DockWidget_qtquick::maximumSize() const { - d->m_controller->onResize(e->size()); - return QWidget::resizeEvent(e); + if (auto guestWidget = widget()) { + // The guests max-size is the same as the widget's, there's no spacing or margins. + return guestWidget->maximumSize(); + } + + return View_qtquick::maximumSize(); +} + +QObject *DockWidget_qtquick::actualTitleBar() const +{ + if (Controllers::Frame *frame = d->q->d->frame()) + return frame->actualTitleBar(); + return nullptr; +} + +QObject *DockWidget_qtquick::actualTitleBarObj() const +{ + return actualTitleBar(); +} + +QQuickItem *DockWidget_qtquick::frameVisualItem() const +{ + if (Controllers::Frame *frame = d->q->d->frame()) { + return frame->visualItem(); + } + + + return nullptr; +} + +void DockWidget_qtquick::onGeometryUpdated() +{ + if (auto frame = qobject_cast(DockWidgetBase::d->frame())) { + frame->updateConstriants(); + frame->updateGeometry(); + } +} + +Frame *DockWidget_qtquick::frame() const +{ + return qobject_cast(DockWidgetBase::d->frame()); } diff --git a/src/qtquick/views/DockWidget_qtquick.h b/src/qtquick/views/DockWidget_qtquick.h index f1e72c3a..d1ebbce9 100644 --- a/src/qtquick/views/DockWidget_qtquick.h +++ b/src/qtquick/views/DockWidget_qtquick.h @@ -16,51 +16,101 @@ * @author Sérgio Martins \ */ -#pragma once +#ifndef KD_DOCKWIDGET_QUICK_H +#define KD_DOCKWIDGET_QUICK_H #include "controllers/DockWidget.h" #include "View_qtquick.h" QT_BEGIN_NAMESPACE class QCloseEvent; +class QQmlEngine; QT_END_NAMESPACE namespace KDDockWidgets { -namespace Views { +namespace Controllers { +class Frame; +class TitleBar; +} +namespace Views { /** * @brief Represents a dock widget. * * Most of the interface lives in DockWidgetBase, to facilitate sharing with QtQuick. */ -class DOCKS_EXPORT DockWidget_qtquick : public View_qtquick +class DOCKS_EXPORT DockWidget_qtquick : public Views::View_qtquick { Q_OBJECT + Q_PROPERTY(QObject *actualTitleBar READ actualTitleBarObj NOTIFY actualTitleBarChanged) public: /** * @brief constructs a new DockWidget - * @param uniqueName Mandatory name that should be unique between all DockWidget instances. - * This name won't be user visible and just used internally for the save/restore. - * Use setTitle() for user visible text. + * @param uniqueName the name of the dockwidget, should be unique. Use title for user visible text. * @param options optional options controlling behaviour + * @param layoutSaverOptions options regarding LayoutSaver behaviour + * @param engine the QML engine this dock widget will be created on. If not specified then + * Config::self().qmlEngine() will be used * * There's no parent argument. The DockWidget is either parented to FloatingWindow or MainWindow - * when visible, or stays without a parent when hidden. This allows to support docking - * to different main windows. + * when visible, or stays without a parent when hidden. */ explicit DockWidget_qtquick(Controllers::DockWidget *controller, - Qt::WindowFlags windowFlags = {}); + Qt::WindowFlags windowFlags = {}, + QQmlEngine *engine = nullptr); ///@brief destructor ~DockWidget_qtquick() override; - Controllers::DockWidget *dockWidget() const; + /// Sets the DockWidget's guest item + /// Similar to DockWidgetBase::setWidget(QQuickItem*) + void setWidget(const QString &qmlFilename); + + /// @reimp + // void setWidget(QQuickItem *widget); + + /// @reimp + Q_INVOKABLE void setWidget(QQuickItem *widget); + + /// @reimp + QSize minSize() const override; + + /// @reimp + QSize maximumSize() const override; + + /// @brief Returns the title bar + QObject *actualTitleBar() const; + + /// @brief Returns the title bar + /// Qt6 requires us to include TitleBar_p.h, so instead the Q_PROPERTY uses + /// QObject so we don't include private headers in public headers + QObject *actualTitleBarObj() const; + + /// @brief Returns the visual item which represents Frame in the screen + /// Equivalent to Frame::visualItem(). + QQuickItem *frameVisualItem() const; + + ///@internal + Q_INVOKABLE KDDockWidgets::Controllers::Frame *frame() const; + + /// @brief Called by QtQuick when min-size changes + Q_INVOKABLE void onGeometryUpdated(); + +Q_SIGNALS: + /// @brief The geometry of the frame container this dock widget is in changed + /// For example, when dragging a dockwidget + void frameGeometryChanged(QRect); + +protected: + bool event(QEvent *e) override; private: - + class Private; + Private *const d; }; } - } + +#endif diff --git a/src/qtquick/views/old/DockWidgetQuick.cpp b/src/qtquick/views/old/DockWidgetQuick.cpp deleted file mode 100644 index d9c956ea..00000000 --- a/src/qtquick/views/old/DockWidgetQuick.cpp +++ /dev/null @@ -1,164 +0,0 @@ -/* - This file is part of KDDockWidgets. - - SPDX-FileCopyrightText: 2019-2022 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 "DockWidgetQuick.h" -#include "FrameworkWidgetFactory.h" - -#include "private/TitleBar_p.h" -#include "private/DockWidget_p.h" -#include "private/quick/FrameQuick_p.h" - -#include -#include -#include - -/** - * @file - * @brief Represents a dock widget. - * - * @author Sérgio Martins \ - */ - -using namespace KDDockWidgets; - -class DockWidgetQuick::Private -{ -public: - Private(DockWidgetQuick *dw, QQmlEngine *qmlengine) - : q(dw) - , m_visualItem(q->createItem(qmlengine, - Config::self().frameworkWidgetFactory()->dockwidgetFilename().toString())) - , m_qmlEngine(qmlengine) - { - Q_ASSERT(m_visualItem); - m_visualItem->setParent(q); - m_visualItem->setParentItem(q); - } - - DockWidgetBase *const q; - QQuickItem *const m_visualItem; - QQmlEngine *const m_qmlEngine; -}; - -DockWidgetQuick::DockWidgetQuick(const QString &name, Options options, - LayoutSaverOptions layoutSaverOptions, QQmlEngine *engine) - : DockWidgetBase(name, options, layoutSaverOptions) - , d(new Private(this, engine ? engine : Config::self().qmlEngine())) -{ - // To mimic what QtWidgets does when creating a new QWidget. - setVisible(false); -} - -DockWidgetQuick::~DockWidgetQuick() -{ - delete d; -} - -void DockWidgetQuick::setWidget(const QString &qmlFilename) -{ - QQuickItem *guest = createItem(d->m_qmlEngine, qmlFilename); - if (!guest) - return; - - setWidget(guest); -} - -void DockWidgetQuick::setWidget(QWidgetAdapter *widget) -{ - widget->QWidgetAdapter::setParent(this); - QWidgetAdapter::makeItemFillParent(widget); - DockWidgetBase::setWidget(widget); -} - -void DockWidgetQuick::setWidget(QQuickItem *guest) -{ - auto adapter = new QWidgetAdapter(this); - adapter->setIsWrapper(); - - // In case the user app needs to use them: - adapter->setProperty("originalParent", QVariant::fromValue(guest->parent())); - adapter->setProperty("originalParentItem", QVariant::fromValue(guest->parentItem())); - - guest->setParentItem(adapter); - guest->setParent(adapter); - QWidgetAdapter::makeItemFillParent(guest); - - setWidget(adapter); -} - -bool DockWidgetQuick::event(QEvent *e) -{ - if (e->type() == QEvent::ParentChange) { - onParentChanged(); - Q_EMIT actualTitleBarChanged(); - } else if (e->type() == QEvent::Show) { - onShown(e->spontaneous()); - } else if (e->type() == QEvent::Hide) { - onHidden(e->spontaneous()); - } else if (e->type() == QEvent::Close) { - onCloseEvent(static_cast(e)); - } - - return DockWidgetBase::event(e); -} - -QSize DockWidgetQuick::minimumSize() const -{ - if (QWidgetAdapter *guestWidget = widget()) { - // The guests min-size is the same as the widget's, there's no spacing or margins. - return guestWidget->minimumSize(); - } - - return DockWidgetBase::minimumSize(); -} - -QSize DockWidgetQuick::maximumSize() const -{ - if (QWidgetAdapter *guestWidget = widget()) { - // The guests max-size is the same as the widget's, there's no spacing or margins. - return guestWidget->maximumSize(); - } - - return DockWidgetBase::maximumSize(); -} - -TitleBar *DockWidgetQuick::actualTitleBar() const -{ - if (Frame *frame = DockWidgetBase::d->frame()) - return frame->actualTitleBar(); - return nullptr; -} - -QObject *DockWidgetQuick::actualTitleBarObj() const -{ - return actualTitleBar(); -} - -QQuickItem *DockWidgetQuick::frameVisualItem() const -{ - if (auto frame = qobject_cast(DockWidgetBase::d->frame())) - return frame->visualItem(); - - return nullptr; -} - -void DockWidgetQuick::onGeometryUpdated() -{ - if (auto frame = qobject_cast(DockWidgetBase::d->frame())) { - frame->updateConstriants(); - frame->updateGeometry(); - } -} - -Frame *DockWidgetQuick::frame() const -{ - return qobject_cast(DockWidgetBase::d->frame()); -} diff --git a/src/qtquick/views/old/DockWidgetQuick.h b/src/qtquick/views/old/DockWidgetQuick.h deleted file mode 100644 index 029fe941..00000000 --- a/src/qtquick/views/old/DockWidgetQuick.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - This file is part of KDDockWidgets. - - SPDX-FileCopyrightText: 2019-2022 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. -*/ - -/** - * @file - * @brief Represents a dock widget. - * - * @author Sérgio Martins \ - */ - -#ifndef KD_DOCKWIDGET_QUICK_H -#define KD_DOCKWIDGET_QUICK_H - -#include "DockWidget.h" - -QT_BEGIN_NAMESPACE -class QCloseEvent; -class QQmlEngine; -QT_END_NAMESPACE - -namespace KDDockWidgets { - -class Frame; -class TitleBar; - -/** - * @brief Represents a dock widget. - * - * Most of the interface lives in DockWidgetBase, to facilitate sharing with QtQuick. - */ -class DOCKS_EXPORT DockWidgetQuick : public DockWidgetBase -{ - Q_OBJECT - Q_PROPERTY(QObject *actualTitleBar READ actualTitleBarObj NOTIFY actualTitleBarChanged) -public: - /** - * @brief constructs a new DockWidget - * @param uniqueName the name of the dockwidget, should be unique. Use title for user visible text. - * @param options optional options controlling behaviour - * @param layoutSaverOptions options regarding LayoutSaver behaviour - * @param engine the QML engine this dock widget will be created on. If not specified then - * Config::self().qmlEngine() will be used - * - * There's no parent argument. The DockWidget is either parented to FloatingWindow or MainWindow - * when visible, or stays without a parent when hidden. - */ - explicit DockWidgetQuick(const QString &uniqueName, Options options = {}, - LayoutSaverOptions layoutSaverOptions = LayoutSaverOptions(), - QQmlEngine *engine = nullptr); - - ///@brief destructor - ~DockWidgetQuick() override; - - /// Sets the DockWidget's guest item - /// Similar to DockWidgetBase::setWidget(QQuickItem*) - void setWidget(const QString &qmlFilename); - - /// @reimp - void setWidget(QWidgetAdapter *widget) override; - - /// @reimp - Q_INVOKABLE void setWidget(QQuickItem *widget); - - /// @reimp - QSize minimumSize() const override; - - /// @reimp - QSize maximumSize() const override; - - /// @brief Returns the title bar - TitleBar *actualTitleBar() const; - - /// @brief Returns the title bar - /// Qt6 requires us to include TitleBar_p.h, so instead the Q_PROPERTY uses - /// QObject so we don't include private headers in public headers - QObject *actualTitleBarObj() const; - - /// @brief Returns the visual item which represents Frame in the screen - /// Equivalent to Frame::visualItem(). - QQuickItem *frameVisualItem() const; - - ///@internal - Q_INVOKABLE KDDockWidgets::Frame *frame() const; - - /// @brief Called by QtQuick when min-size changes - Q_INVOKABLE void onGeometryUpdated(); - -Q_SIGNALS: - /// @brief The geometry of the frame container this dock widget is in changed - /// For example, when dragging a dockwidget - void frameGeometryChanged(QRect); - -protected: - bool event(QEvent *e) override; - -private: - class Private; - Private *const d; -}; - -} - -#endif