diff --git a/examples/qtquick/dockwidgets/Another.qml b/examples/qtquick/dockwidgets/Another.qml new file mode 100644 index 00000000..93937137 --- /dev/null +++ b/examples/qtquick/dockwidgets/Another.qml @@ -0,0 +1,18 @@ +/* + This file is part of KDDockWidgets. + + SPDX-FileCopyrightText: 2020 Klarälvdalens Datakonsult AB, a KDAB Group company + Author: Sergio Martins + + SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only + + Contact KDAB at for commercial licensing options. +*/ + +import QtQuick 2.9 + +Rectangle { + id: root + color: "green" + anchors.fill: parent +} diff --git a/examples/qtquick/dockwidgets/Guest1.qml b/examples/qtquick/dockwidgets/Guest1.qml index 102a9399..ac7e758e 100644 --- a/examples/qtquick/dockwidgets/Guest1.qml +++ b/examples/qtquick/dockwidgets/Guest1.qml @@ -10,9 +10,38 @@ */ import QtQuick 2.9 +import QtQuick.Controls 2.12 +import com.kdab.dockwidgets 1.0 as KDDW Guest { anchors.fill: parent background: "qrc:/assets/triangles.png" logo: "qrc:/assets/KDAB_bubble_white.png" + + KDDW.DockWidget { + id: another + uniqueName: "another1" + source: ":/Another.qml" + } + + Button { + text: "Toggle Another" + anchors { + bottom: parent.bottom + left: parent.left + margins: 5 + } + + onClicked: { + + if (another.dockWidget.visible) { + another.dockWidget.close(); + } else { + another.dockWidget.show(); + } + + + } + } + } diff --git a/examples/qtquick/dockwidgets/resources_qtquick_example.qrc b/examples/qtquick/dockwidgets/resources_qtquick_example.qrc index f80890cb..d7b631cd 100644 --- a/examples/qtquick/dockwidgets/resources_qtquick_example.qrc +++ b/examples/qtquick/dockwidgets/resources_qtquick_example.qrc @@ -5,5 +5,6 @@ Guest2.qml Guest3.qml Guest.qml + Another.qml diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index bc842393..dc1ded5e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -87,6 +87,7 @@ set(DOCKS_INSTALLABLE_PRIVATE_WIDGET_INCLUDES if(${PROJECT_NAME}_QTQUICK) set(DOCKSLIBS_SRCS ${DOCKSLIBS_SRCS} DockWidgetQuick.cpp + private/quick/DockWidgetInstantiator.cpp private/quick/QWidgetAdapter_quick.cpp private/quick/FloatingWindowQuick.cpp private/quick/TitleBarQuick.cpp diff --git a/src/DockWidgetBase.h b/src/DockWidgetBase.h index 57d352ba..f151134e 100644 --- a/src/DockWidgetBase.h +++ b/src/DockWidgetBase.h @@ -328,7 +328,7 @@ public: * @brief Like QWidget::close() but the hosted widget won't be asked if we * should close. */ - void forceClose(); + Q_INVOKABLE void forceClose(); /** * @brief Returns this dock widget's title bar. @@ -373,7 +373,7 @@ public: QStringList affinities() const; /// @brief Equivalent to QWidget::show(), but it's optimized to reduce flickering on some platforms - void show(); + Q_INVOKABLE void show(); /// @brief Brings the dock widget to the front. /// @@ -382,7 +382,7 @@ public: /// - If the dock widget is floating, QWindow::raise() is called. /// /// This only applies if the dock widget is already open. If closed, does nothing. - void raise(); + Q_INVOKABLE void raise(); /** * @brief Returns whether widget() is a KDDockWidget::MainWindow diff --git a/src/DockWidgetQuick.cpp b/src/DockWidgetQuick.cpp index 1dd8296b..872f28a5 100644 --- a/src/DockWidgetQuick.cpp +++ b/src/DockWidgetQuick.cpp @@ -66,7 +66,7 @@ void DockWidgetQuick::setWidget(const QString &qmlFilename) setWidget(adapter); } -void DockWidgetQuick::setWidget(QWidgetOrQuick *widget) +void DockWidgetQuick::setWidget(QWidgetAdapter *widget) { widget->QWidgetAdapter::setParent(this); QWidgetAdapter::makeItemFillParent(widget); diff --git a/src/DockWidgetQuick.h b/src/DockWidgetQuick.h index 7c9a9f38..0cb27b98 100644 --- a/src/DockWidgetQuick.h +++ b/src/DockWidgetQuick.h @@ -55,7 +55,7 @@ public: void setWidget(const QString &qmlFilename); /// @reimp - void setWidget(QWidgetOrQuick *widget) override; + void setWidget(QWidgetAdapter *widget) override; /// @reimp QSize minimumSize() const override; diff --git a/src/private/DockRegistry.cpp b/src/private/DockRegistry.cpp index c005233d..8bf8f5f6 100644 --- a/src/private/DockRegistry.cpp +++ b/src/private/DockRegistry.cpp @@ -328,6 +328,11 @@ void DockRegistry::unregisterFrame(Frame *frame) m_frames.removeOne(frame); } +bool DockRegistry::containsDockWidget(const QString &uniqueName) const +{ + return dockByName(uniqueName) != nullptr; +} + DockWidgetBase *DockRegistry::dockByName(const QString &name) const { for (auto dock : qAsConst(m_dockWidgets)) { diff --git a/src/private/DockRegistry_p.h b/src/private/DockRegistry_p.h index 0ff20b63..74157c3c 100644 --- a/src/private/DockRegistry_p.h +++ b/src/private/DockRegistry_p.h @@ -53,6 +53,7 @@ public: DockWidgetBase *focusedDockWidget() const; + bool containsDockWidget(const QString &uniqueName) const; DockWidgetBase *dockByName(const QString &) const; MainWindowBase *mainWindowByName(const QString &) const; diff --git a/src/private/quick/DockWidgetInstantiator.cpp b/src/private/quick/DockWidgetInstantiator.cpp new file mode 100644 index 00000000..85bdb5bf --- /dev/null +++ b/src/private/quick/DockWidgetInstantiator.cpp @@ -0,0 +1,76 @@ +/* + This file is part of KDDockWidgets. + + SPDX-FileCopyrightText: 2019-2020 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 "DockWidgetInstantiator_p.h" +#include "DockWidgetQuick.h" +#include "DockRegistry_p.h" + +using namespace KDDockWidgets; + +QString DockWidgetInstantiator::uniqueName() const +{ + return m_uniqueName; +} + +void DockWidgetInstantiator::setUniqueName(const QString &name) +{ + m_uniqueName = name; + Q_EMIT uniqueNameChanged(); +} + +QString DockWidgetInstantiator::source() const +{ + return m_sourceFilename; +} + +void DockWidgetInstantiator::setSource(const QString &source) +{ + m_sourceFilename = source; + Q_EMIT sourceChanged(); +} + +DockWidgetQuick *DockWidgetInstantiator::dockWidget() const +{ + return m_dockWidget; +} + +void DockWidgetInstantiator::classBegin() +{ + // Nothing interesting to do here. +} + +void DockWidgetInstantiator::componentComplete() +{ + if (m_uniqueName.isEmpty()) { + qWarning() << Q_FUNC_INFO << "Each DockWidget need an unique name. Set the uniqueName property."; + return; + } + + if (DockRegistry::self()->containsDockWidget(m_uniqueName)) { + // Dock widget already exists. all good. + return; + } + + if (m_dockWidget) { + qWarning() << Q_FUNC_INFO << "Unexpected bug."; + return; + } + + if (m_sourceFilename.isEmpty()) { + qWarning() << Q_FUNC_INFO << "the 'source' property must be set."; + return; + } + + m_dockWidget = new DockWidgetQuick(m_uniqueName); + m_dockWidget->setWidget(m_sourceFilename); + + Q_EMIT dockWidgetChanged(); +} diff --git a/src/private/quick/DockWidgetInstantiator_p.h b/src/private/quick/DockWidgetInstantiator_p.h new file mode 100644 index 00000000..29b1b130 --- /dev/null +++ b/src/private/quick/DockWidgetInstantiator_p.h @@ -0,0 +1,64 @@ +/* + This file is part of KDDockWidgets. + + SPDX-FileCopyrightText: 2019-2020 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 +#include +#include + +namespace KDDockWidgets { + +class DockWidgetQuick; + +/** + * @brief Indirection helper to instantiate dock widgets from QML + * + * "DockWidget {}" in QML won't create a KDDockWidget::DockWidget directly, but instead an + * DockWidgetInstantiator. DockWidgetInstantiator will then create the DockWidget instance only + * when the QML parsing ends (and all propreties are set) + * + * This allows to pass the correct uniqueName to DockWidget's ctor. + */ +class DockWidgetInstantiator + : public QObject + , public QQmlParserStatus +{ + Q_OBJECT + Q_INTERFACES(QQmlParserStatus) + Q_PROPERTY(QString uniqueName READ uniqueName WRITE setUniqueName NOTIFY uniqueNameChanged) + Q_PROPERTY(QString source READ source WRITE setSource NOTIFY sourceChanged) + Q_PROPERTY(KDDockWidgets::DockWidgetQuick *dockWidget READ dockWidget NOTIFY dockWidgetChanged) +public: + QString uniqueName() const; + void setUniqueName(const QString &); + + QString source() const; + void setSource(const QString &); + + DockWidgetQuick *dockWidget() const; + +protected: + void classBegin() override; + void componentComplete() override; + +Q_SIGNALS: + void uniqueNameChanged(); + void sourceChanged(); + void dockWidgetChanged(); +private: + QString m_uniqueName; + QString m_sourceFilename; + DockWidgetQuick *m_dockWidget = nullptr; + +}; + +} diff --git a/src/private/quick/QWidgetAdapter_quick_p.h b/src/private/quick/QWidgetAdapter_quick_p.h index cbca59d1..2add0616 100644 --- a/src/private/quick/QWidgetAdapter_quick_p.h +++ b/src/private/quick/QWidgetAdapter_quick_p.h @@ -122,9 +122,9 @@ public: bool isTopLevel() const { return isWindow(); } bool isMaximized() const; bool isActiveWindow() const; - void showMaximized(); - void showMinimized(); - void showNormal(); + Q_INVOKABLE void showMaximized(); + Q_INVOKABLE void showMinimized(); + Q_INVOKABLE void showNormal(); QQuickView *quickView() const; QWindow *windowHandle() const; @@ -138,7 +138,7 @@ public: void setWindowTitle(const QString &); void setWindowIcon(const QIcon &); - bool close(); + Q_INVOKABLE bool close(); QQuickItem *childAt(QPoint) const; void move(int x, int y); void move(QPoint); diff --git a/src/private/quick/QmlTypes.cpp b/src/private/quick/QmlTypes.cpp index a0c94fa8..bc9f998c 100644 --- a/src/private/quick/QmlTypes.cpp +++ b/src/private/quick/QmlTypes.cpp @@ -12,6 +12,7 @@ #include "QmlTypes.h" #include "DropAreaWithCentralFrame_p.h" #include "quick/MainWindowWrapper_p.h" +#include "quick/DockWidgetInstantiator_p.h" #include "DropIndicatorOverlayInterface_p.h" #include "TitleBar_p.h" #include "indicators/ClassicIndicators_p.h" @@ -23,6 +24,7 @@ void KDDockWidgets::registerQmlTypes() { qmlRegisterType("com.kdab.dockwidgets", 1, 0, "DropAreaWithCentralFrame"); qmlRegisterType("com.kdab.dockwidgets", 1, 0, "MainWindow"); + qmlRegisterType("com.kdab.dockwidgets", 1, 0, "DockWidget"); qmlRegisterUncreatableType("com.kdab.dockwidgets", 1, 0, "TitleBar", QStringLiteral("Enum access only")); qmlRegisterUncreatableType("com.kdab.dockwidgets", 1, 0, "DropIndicatorOverlayInterface", QStringLiteral("Enum access only"));