Skip to content

Commit

Permalink
feat: add AppletBridge to connect applets
Browse files Browse the repository at this point in the history
We add AppletProxy to export Applet's signals and slots.
AppletMetaProxy as QObject's router for signals and slots.

task: https://pms.uniontech.com/task-view-365219.html
  • Loading branch information
18202781743 committed Oct 21, 2024
1 parent fe0d038 commit b4d88ce
Show file tree
Hide file tree
Showing 16 changed files with 409 additions and 1 deletion.
7 changes: 6 additions & 1 deletion example/applet-example-data/exampleapplet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ bool ExampleApplet::load()
{
DCORE_USE_NAMESPACE;
std::unique_ptr<DConfig> config(DConfig::create("org.deepin.dde.shell", "org.deepin.ds.example"));
return config->value("loadAppletExampleData").toBool();
return config->value("loadAppletExampleData", true).toBool();
}

bool ExampleApplet::init()
Expand Down Expand Up @@ -56,6 +56,11 @@ void ExampleApplet::setUserData(bool newUserData)
emit userDataChanged();
}

QString ExampleApplet::call(const QString &id)
{
return id + QString("-done");
}

D_APPLET_CLASS(ExampleApplet)

#include "exampleapplet.moc"
3 changes: 3 additions & 0 deletions example/applet-example-data/exampleapplet.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,12 @@ class ExampleApplet : public DApplet
bool userData() const;
void setUserData(bool newUserData);

Q_INVOKABLE QString call(const QString &id);

Q_SIGNALS:
void mainTextChanged();
void userDataChanged();
void sendSignal(const QString &id);
private:
QString m_mainText;
bool m_userData;
Expand Down
6 changes: 6 additions & 0 deletions example/containment-example/examplecontainment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include "pluginfactory.h"
#include "pluginloader.h"
#include "appletproxy.h"
#include <DConfig>
#include <QJsonDocument>
#include <QJsonArray>
Expand Down Expand Up @@ -67,6 +68,11 @@ bool ExampleContainment::load()
return DApplet::load();
}

QObject *ExampleContainment::createProxyMeta()

Check warning on line 71 in example/containment-example/examplecontainment.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

The function 'createProxyMeta' is never used.
{
return new ExampleAppletProxy(this);
}

DPluginMetaData ExampleContainment::targetPlugin() const
{
auto children = DPluginLoader::instance()->childrenPlugin(pluginId());
Expand Down
17 changes: 17 additions & 0 deletions example/containment-example/examplecontainment.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,21 @@

DS_USE_NAMESPACE

class ExampleAppletProxy : public QObject
{
Q_OBJECT
public:
ExampleAppletProxy(QObject *parent = nullptr)
: QObject(parent)
{

}
Q_INVOKABLE QString call(const QString &id)
{
return id + QString("-done");
}
};

class ExampleContainment : public DContainment
{
Q_OBJECT
Expand All @@ -16,6 +31,8 @@ class ExampleContainment : public DContainment
~ExampleContainment();

virtual bool load() override;
protected:
virtual QObject *createProxyMeta() override;
private:
DPluginMetaData targetPlugin() const;
};
35 changes: 35 additions & 0 deletions example/panel-example/examplepanel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "examplepanel.h"

#include "pluginfactory.h"
#include "appletbridge.h"

ExamplePanel::ExamplePanel(QObject *parent)
: DPanel(parent)
Expand All @@ -19,6 +20,35 @@ bool ExamplePanel::load()
bool ExamplePanel::init()
{
DPanel::init();

DAppletBridge bridge("org.deepin.ds.example.applet-data");

Check warning on line 24 in example/panel-example/examplepanel.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Local variable 'bridge' shadows outer variable

qDebug() << "It's state of the bridge:" << bridge.isValid();
if (auto applet = bridge.applet()) {
qDebug() << "Get property:" << applet->property("mainText");
QString id("call");
qDebug() << "Invoke argument:" << id;
qDebug() << "Invoke method staus:" << QMetaObject::invokeMethod(applet, "call", Qt::DirectConnection,
Q_RETURN_ARG(QString, id), Q_ARG(const QString&, id));
qDebug() << "Invoked returd value:" << id;

QObject::connect(applet, SIGNAL(sendSignal(const QString &)), SLOT(onReceivedSignal(const QString &)));

QMetaObject::invokeMethod(applet, "sendSignal", Qt::DirectConnection, Q_ARG(const QString&, id));
}

{
DAppletBridge bridge("org.deepin.ds.example.containment");
qDebug() << "Customize MetaObject of the applet:" << bridge.isValid();
if (auto applet = bridge.applet()) {
QString id("call");
qDebug() << "Invoke argument:" << id;
qDebug() << "Invoke method staus:" << QMetaObject::invokeMethod(applet, "call", Qt::DirectConnection,
Q_RETURN_ARG(QString, id), Q_ARG(const QString&, id));
qDebug() << "Invoked returd value:" << id;
}
}

QObject::connect(this, &DApplet::rootObjectChanged, this, [this]() {
Q_ASSERT(rootObject());
Q_ASSERT(window());
Expand All @@ -27,6 +57,11 @@ bool ExamplePanel::init()
return true;
}

void ExamplePanel::onReceivedSignal(const QString &id)

Check warning on line 60 in example/panel-example/examplepanel.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

The function 'onReceivedSignal' is never used.
{
qDebug() << "Received signal:" << id;
}

D_APPLET_CLASS(ExamplePanel)

#include "examplepanel.moc"
4 changes: 4 additions & 0 deletions example/panel-example/examplepanel.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,8 @@ class ExamplePanel : public DPanel
virtual bool load() override;

virtual bool init() override;

private slots:
void onReceivedSignal(const QString &id);

};
6 changes: 6 additions & 0 deletions frame/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ set(PUBLIC_HEADERS
appletdata.h
containment.h
panel.h
appletproxy.h
appletbridge.h
qmlengine.h
layershell/dlayershellwindow.h
dsutility.h
Expand All @@ -21,6 +23,8 @@ set(PRIVATE_HEADERS
private/containment_p.h
private/panel_p.h
private/appletitem_p.h
private/appletproxy_p.h
private/appletbridge_p.h
private/dsqmlglobal_p.h
layershell/qwaylandlayershellsurface_p.h
layershell/qwaylandlayershellintegration_p.h
Expand Down Expand Up @@ -50,6 +54,8 @@ add_library(dde-shell-frame SHARED
applet.cpp
containment.cpp
panel.cpp
appletproxy.cpp
appletbridge.cpp
appletitem.cpp
containmentitem.cpp
qmlengine.cpp
Expand Down
17 changes: 17 additions & 0 deletions frame/applet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include "applet.h"
#include "private/applet_p.h"
#include "private/appletproxy_p.h"

#include <QLoggingCategory>
#include <QUuid>
Expand All @@ -26,6 +27,16 @@ DAppletPrivate::~DAppletPrivate()
}
}

DAppletProxy *DAppletPrivate::appletProxy() const
{
if (!m_proxy) {
auto meta = const_cast<DAppletPrivate *>(this)->q_func()->createProxyMeta();
const_cast<DAppletPrivate *>(this)->m_proxy =
new DAppletMetaProxy(meta, const_cast<DAppletPrivate *>(this)->q_func());
}
return m_proxy;
}

DApplet::DApplet(QObject *parent)
: DApplet(*new DAppletPrivate(this), parent)
{
Expand Down Expand Up @@ -109,4 +120,10 @@ bool DApplet::init()
return true;
}

QObject *DApplet::createProxyMeta()
{
D_DC(DApplet);
return this;
}

DS_END_NAMESPACE
3 changes: 3 additions & 0 deletions frame/applet.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ DS_BEGIN_NAMESPACE
*/
class DAppletPrivate;
class DPluginLoader;
class DAppletBridge;
class DS_SHARE DApplet : public QObject, public DTK_CORE_NAMESPACE::DObject
{
Q_OBJECT
Expand All @@ -26,6 +27,7 @@ class DS_SHARE DApplet : public QObject, public DTK_CORE_NAMESPACE::DObject
Q_PROPERTY(QObject *rootObject READ rootObject NOTIFY rootObjectChanged)
D_DECLARE_PRIVATE(DApplet)

Check warning on line 28 in frame/applet.h

View workflow job for this annotation

GitHub Actions / cppcheck

There is an unknown macro here somewhere. Configuration is required. If D_DECLARE_PRIVATE is a macro then please configure it.
friend class DPluginLoader;
friend class DAppletBridge;
public:
explicit DApplet(QObject *parent = nullptr);
virtual ~DApplet() override;
Expand All @@ -48,6 +50,7 @@ class DS_SHARE DApplet : public QObject, public DTK_CORE_NAMESPACE::DObject

protected:
explicit DApplet(DAppletPrivate &dd, QObject *parent = nullptr);
virtual QObject *createProxyMeta();

private:
void setMetaData(const DPluginMetaData &metaData);
Expand Down
95 changes: 95 additions & 0 deletions frame/appletbridge.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later

#include "appletbridge.h"
#include "containment.h"
#include "private/appletbridge_p.h"
#include "private/applet_p.h"

#include "pluginloader.h"
#include <QQueue>

DS_BEGIN_NAMESPACE

DAppletBridgePrivate::DAppletBridgePrivate(DAppletBridge *qq)
: DTK_CORE_NAMESPACE::DObjectPrivate(qq)
{
}

DAppletBridgePrivate::~DAppletBridgePrivate()
{
}

QList<DApplet *> DAppletBridgePrivate::applets() const
{
QList<DApplet *> applets;
auto rootApplet = DPluginLoader::instance()->rootApplet();
auto root = qobject_cast<DContainment *>(rootApplet);

QQueue<DContainment *> containments;
containments.enqueue(root);
while (!containments.isEmpty()) {
DContainment *containment = containments.dequeue();
for (const auto applet : containment->applets()) {
if (auto item = qobject_cast<DContainment *>(applet)) {
containments.enqueue(item);
}
if (applet->pluginId() == m_pluginId)
applets << applet;
}
}
return applets;
}

DAppletBridge::DAppletBridge(const QString &pluginId, QObject *parent)
: DAppletBridge(*new DAppletBridgePrivate(this), parent)
{
d_func()->m_pluginId = pluginId;
}

DAppletBridge::DAppletBridge(DAppletBridgePrivate &dd, QObject *parent)
: QObject(parent)
, DObject(dd)
{
}

DAppletBridge::~DAppletBridge()
{
}

bool DAppletBridge::isValid() const
{
D_DC(DAppletBridge);
const auto plugin = DPluginLoader::instance()->plugin(d->m_pluginId);
return plugin.isValid();
}

QList<DAppletProxy *> DAppletBridge::applets() const
{
D_DC(DAppletBridge);
if (!isValid())
return {};
QList<DAppletProxy *> ret;
for (const auto item : d->applets()) {
if (auto proxy = item->d_func()->appletProxy()) {
ret << proxy;
}
}
return ret;
}

DAppletProxy *DAppletBridge::applet() const
{
D_DC(DAppletBridge);
if (!isValid())
return {};
for (const auto item : d->applets()) {
if (auto proxy = item->d_func()->appletProxy()) {
return proxy;
}
}
return nullptr;
}

DS_END_NAMESPACE
35 changes: 35 additions & 0 deletions frame/appletbridge.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later

#pragma once

#include "dsglobal.h"
#include "appletproxy.h"

#include <QObject>
#include <DObject>

DS_BEGIN_NAMESPACE
/**
* @brief Interacting with other applets
*/
class DAppletBridgePrivate;
class DS_SHARE DAppletBridge : public QObject, public DTK_CORE_NAMESPACE::DObject
{
Q_OBJECT
D_DECLARE_PRIVATE(DAppletBridge)
public:
explicit DAppletBridge(const QString &pluginId, QObject *parent = nullptr);
virtual ~DAppletBridge() override;

bool isValid() const;

QList<DAppletProxy *> applets() const;
DAppletProxy *applet() const;

protected:
explicit DAppletBridge(DAppletBridgePrivate &dd, QObject *parent = nullptr);
};

DS_END_NAMESPACE
Loading

0 comments on commit b4d88ce

Please sign in to comment.