diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 000000000..1e20521d8 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,72 @@ +# SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +# +# SPDX-License-Identifier: CC0-1.0 + +CMAKE_MINIMUM_REQUIRED(VERSION 3.10) + +set(VERSION 3.7) + +set(DS_VERSION "1.0.0" CACHE STRING "Define project version") +project(DDEShell + VERSION "${DS_VERSION}" + DESCRIPTION "dde-shell" + HOMEPAGE_URL "https://github.com/linuxdeepin/dde-shell" + LANGUAGES CXX +) + +set(CMAKE_CXX_STANDARD 17) +if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX /usr) +endif () + +set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_AUTORCC ON) +set(CMAKE_AUTOMOC ON) +set(CMAKE_INCLUDE_CURRENT_DIR ON) +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + +set(DS_BUILD_WITH_QT6 ON CACHE BOOL "Build dde-shell with Qt6") + +if (DS_BUILD_WITH_QT6) + set(QT_VERSION_MAJOR 6) + set(DTK_VERSION_MAJOR 6) +else() + set(QT_VERSION_MAJOR 5) + set(DTK_VERSION_MAJOR "") +endif() + +include(GNUInstallDirs) +include(CMakePackageConfigHelpers) + +set(LIB_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}" CACHE STRING "Library install path") +set(DDE_SHELL_PACKAGE_INSTALL_DIR share/dde-shell CACHE STRING "Package install path") +set(DDE_SHELL_PLUGIN_INSTALL_DIR ${CMAKE_INSTALL_LIBDIR}/dde-shell CACHE STRING "Plugin install path") +set(INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_INCLUDEDIR}/dde-shell" CACHE STRING "Headers install path") +set(CONFIG_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/DDEShell" CACHE STRING "CMake config file install directory") +set(QML_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}/qt${QT_VERSION_MAJOR}/qml" CACHE STRING "Qml plugin install directory") + +list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake") +include(DDEShellPackageMacros) + +find_package(Qt${QT_VERSION_MAJOR} ${REQUIRED_QT_VERSION} REQUIRED COMPONENTS Core Gui Concurrent Quick) +find_package(Dtk${DTK_VERSION_MAJOR} REQUIRED COMPONENTS Core Gui) + +add_subdirectory(frame) +add_subdirectory(shell) +add_subdirectory(example) + +configure_package_config_file( + "${CMAKE_CURRENT_LIST_DIR}/misc/DDEShellConfig.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/DDEShellConfig.cmake" + INSTALL_DESTINATION "${CONFIG_INSTALL_DIR}" +) +write_basic_package_version_file( + "${CMAKE_CURRENT_BINARY_DIR}/DDEShellConfigVersion.cmake" + VERSION ${VERSION} + COMPATIBILITY SameMajorVersion +) +# Install cmake config file +install(FILES "${PROJECT_SOURCE_DIR}/cmake/DDEShellPackageMacros.cmake" DESTINATION "${CONFIG_INSTALL_DIR}") +install(FILES "${CMAKE_CURRENT_BINARY_DIR}/DDEShellConfig.cmake" DESTINATION "${CONFIG_INSTALL_DIR}") +install(FILES "${CMAKE_CURRENT_BINARY_DIR}/DDEShellConfigVersion.cmake" DESTINATION "${CONFIG_INSTALL_DIR}") diff --git a/cmake/DDEShellPackageMacros.cmake b/cmake/DDEShellPackageMacros.cmake new file mode 100644 index 000000000..58b657ff4 --- /dev/null +++ b/cmake/DDEShellPackageMacros.cmake @@ -0,0 +1,36 @@ +include(CMakeParseArguments) + +macro(ds_build_package) + set(oneValueArgs PACKAGE TARGET PACKAGE_ROOT_DIR) + cmake_parse_arguments(_config "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + set(package_root_dir ${CMAKE_CURRENT_SOURCE_DIR}/package) + if (DEFINED _config_PACKAGE_ROOT_DIR) + set(package_root_dir ${CMAKE_CURRENT_SOURCE_DIR}/${_config_PACKAGE_ROOT_DIR}) + endif() + file(GLOB_RECURSE package_files ${package_root_dir}/*) + add_custom_target(${_config_PACKAGE}_package ALL + SOURCES ${package_files} + ) + set(package_dirs ${PROJECT_BINARY_DIR}/packages/${_config_PACKAGE}/) + add_custom_command(TARGET ${_config_PACKAGE}_package + COMMAND ${CMAKE_COMMAND} -E copy_directory ${package_root_dir} ${package_dirs} + ) + + if (DEFINED _config_TARGET) + set_target_properties(${_config_TARGET} PROPERTIES + PREFIX "" + OUTPUT_NAME ${_config_PACKAGE} + LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/plugins/ + ) + endif() +endmacro() + +function(ds_install_package) + ds_build_package(${ARGN}) + install(DIRECTORY ${package_dirs} DESTINATION ${DDE_SHELL_PACKAGE_INSTALL_DIR}/${_config_PACKAGE}) + + if (DEFINED _config_TARGET) + install(TARGETS ${_config_TARGET} DESTINATION ${DDE_SHELL_PLUGIN_INSTALL_DIR}/) + endif() +endfunction() diff --git a/debian/control b/debian/control new file mode 100644 index 000000000..01403ff3a --- /dev/null +++ b/debian/control @@ -0,0 +1,42 @@ +Source: dde-shell +Section: unknown +Priority: optional +Maintainer: Deepin Packages Builder +Build-Depends: + debhelper-compat ( =12), + cmake, + qt6-base-dev, + qt6-declarative-dev, + qt6-base-dev-tools, + qt6-tools-dev, + libdtk6gui-dev, + libdtk6core-dev, + libdtkcommon-dev, +Standards-Version: 3.9.8 +Homepage: http://www.deepin.org + +Package: libdde-shell +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends}, + libdtkcore5 +Multi-Arch: same +Description: + +Package: libdde-shell-dev +Architecture: any +Depends: ${misc:Depends}, libdde-shell( =${binary:Version}) +Description: + + +Package: dde-shell +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends}, libdde-shell( =${binary:Version}) +Multi-Arch: same +Description: + +Package: dde-shell-example +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends}, libdde-shell( =${binary:Version}) +Multi-Arch: same +Description: + diff --git a/debian/dde-shell-example.install b/debian/dde-shell-example.install new file mode 100644 index 000000000..86524f375 --- /dev/null +++ b/debian/dde-shell-example.install @@ -0,0 +1,2 @@ +usr/lib/*/*dde-shell/* +usr/share/dde-shell/* diff --git a/debian/dde-shell.install b/debian/dde-shell.install new file mode 100644 index 000000000..1df36c612 --- /dev/null +++ b/debian/dde-shell.install @@ -0,0 +1 @@ +usr/bin/* diff --git a/debian/libdde-shell-dev.install b/debian/libdde-shell-dev.install new file mode 100644 index 000000000..dc193a9b8 --- /dev/null +++ b/debian/libdde-shell-dev.install @@ -0,0 +1,3 @@ +usr/lib/*/lib*.so +usr/include +usr/lib/*/cmake/*/*.cmake diff --git a/debian/libdde-shell.install b/debian/libdde-shell.install new file mode 100644 index 000000000..c93ae8bf4 --- /dev/null +++ b/debian/libdde-shell.install @@ -0,0 +1,2 @@ +usr/lib/*/lib*.so.* +usr/lib/*/qt6/qml/org/deepin/ds/* diff --git a/debian/rules b/debian/rules new file mode 100755 index 000000000..9e9f42344 --- /dev/null +++ b/debian/rules @@ -0,0 +1,17 @@ +#!/usr/bin/make -f +DPKG_EXPORT_BUILDFLAGS = 1 +include /usr/share/dpkg/default.mk +export QT_SELECT = qt5 + +DEB_HOST_MULTIARCH ?= $(shell dpkg-architecture -qDEB_HOST_MULTIARCH) + +VERSION = $(DEB_VERSION_UPSTREAM) +PACK_VER = $(shell echo $(VERSION) | awk -F'[+_~-]' '{print $$1}') +# Fix: invalid digit "8" in octal constant. e.g. u008 ==> 008 ==> 8 +BUILD_VER = $(shell echo $(VERSION) | awk -F'[+_~-]' '{print $$2}' | sed 's/[^0-9]//g' | awk '{print int($$1)}') + +%: + dh $@ + +override_dh_auto_configure: + dh_auto_configure -- -DDS_VERSION=${PACK_VER} diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt new file mode 100644 index 000000000..fa0a90eda --- /dev/null +++ b/example/CMakeLists.txt @@ -0,0 +1,10 @@ +# SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +# +# SPDX-License-Identifier: GPL-3.0-or-later + +find_package(Qt${QT_VERSION_MAJOR} ${REQUIRED_QT_VERSION} REQUIRED COMPONENTS Core Gui Quick) + +add_subdirectory(applet-example) +add_subdirectory(applet-example-data) +add_subdirectory(containment-example) +add_subdirectory(corona-example) diff --git a/example/applet-example-data/CMakeLists.txt b/example/applet-example-data/CMakeLists.txt new file mode 100644 index 000000000..c730eb77b --- /dev/null +++ b/example/applet-example-data/CMakeLists.txt @@ -0,0 +1,14 @@ +# SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +# +# SPDX-License-Identifier: GPL-3.0-or-later + +add_library(ds-example-applet-data SHARED + exampleapplet.h + exampleapplet.cpp +) + +target_link_libraries(ds-example-applet-data PRIVATE + dde-shell-frame +) + +ds_install_package(PACKAGE org.deepin.ds.applet-example-data TARGET ds-example-applet-data) diff --git a/example/applet-example-data/exampleapplet.cpp b/example/applet-example-data/exampleapplet.cpp new file mode 100644 index 000000000..41aed9198 --- /dev/null +++ b/example/applet-example-data/exampleapplet.cpp @@ -0,0 +1,23 @@ +// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "exampleapplet.h" + +#include "pluginfactory.h" + +ExampleApplet::ExampleApplet(QObject *parent) + : DApplet(parent) + , m_mainText("Custom Applet") +{ + +} + +QString ExampleApplet::mainText() const +{ + return m_mainText; +} + +D_APPLET_CLASS(ExampleApplet) + +#include "exampleapplet.moc" diff --git a/example/applet-example-data/exampleapplet.h b/example/applet-example-data/exampleapplet.h new file mode 100644 index 000000000..6e5f74524 --- /dev/null +++ b/example/applet-example-data/exampleapplet.h @@ -0,0 +1,21 @@ +// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include "applet.h" + +DS_USE_NAMESPACE + +class Q_DECL_EXPORT ExampleApplet : public DApplet +{ + Q_OBJECT + Q_PROPERTY(QString mainText READ mainText CONSTANT) +public: + ExampleApplet(QObject *parent = nullptr); + + QString mainText() const; +private: + QString m_mainText; +}; diff --git a/example/applet-example-data/package/main.qml b/example/applet-example-data/package/main.qml new file mode 100644 index 000000000..3eda3426f --- /dev/null +++ b/example/applet-example-data/package/main.qml @@ -0,0 +1,22 @@ +// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +import QtQuick 2.11 +import QtQuick.Controls 2.15 + +import org.deepin.ds 1.0 + +AppletItem { + objectName: "appplet data" + implicitWidth: 200 + implicitHeight: 100 + Rectangle { + anchors.fill: parent + color: "gray" + Text { + anchors.centerIn: parent + text: Applet.mainText + } + } +} \ No newline at end of file diff --git a/example/applet-example-data/package/metadata.json b/example/applet-example-data/package/metadata.json new file mode 100644 index 000000000..27b121270 --- /dev/null +++ b/example/applet-example-data/package/metadata.json @@ -0,0 +1,8 @@ +{ + "Plugin": { + "Version": "1.0", + "Id": "org.deepin.ds.applet-example-data", + "Url": "main.qml", + "Parent": "org.deepin.ds.containment-example" + } +} diff --git a/example/applet-example/CMakeLists.txt b/example/applet-example/CMakeLists.txt new file mode 100644 index 000000000..e68984781 --- /dev/null +++ b/example/applet-example/CMakeLists.txt @@ -0,0 +1,5 @@ +# SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +# +# SPDX-License-Identifier: GPL-3.0-or-later + +ds_install_package(PACKAGE org.deepin.ds.applet-example) diff --git a/example/applet-example/package/control/TextEx.qml b/example/applet-example/package/control/TextEx.qml new file mode 100644 index 000000000..b7c3b32ae --- /dev/null +++ b/example/applet-example/package/control/TextEx.qml @@ -0,0 +1,10 @@ +// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +import QtQuick 2.11 +import QtQuick.Controls 2.4 + +Text { + color: "cyan" +} \ No newline at end of file diff --git a/example/applet-example/package/main.qml b/example/applet-example/package/main.qml new file mode 100644 index 000000000..bed43d90d --- /dev/null +++ b/example/applet-example/package/main.qml @@ -0,0 +1,23 @@ +// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +import QtQuick 2.11 +import QtQuick.Controls 2.4 + +import org.deepin.ds 1.0 +import "control" + +AppletItem { + objectName: "appplet item" + implicitWidth: 100 + implicitHeight: 100 + Rectangle { + anchors.fill: parent + color: "green" + TextEx { + anchors.centerIn: parent + text: "Hello world" + } + } +} \ No newline at end of file diff --git a/example/applet-example/package/metadata.json b/example/applet-example/package/metadata.json new file mode 100644 index 000000000..9dea23d53 --- /dev/null +++ b/example/applet-example/package/metadata.json @@ -0,0 +1,8 @@ +{ + "Plugin": { + "Version": "1.0", + "Id": "org.deepin.ds.applet-example", + "Url": "main.qml", + "Parent": "org.deepin.ds.containment-example" + } +} diff --git a/example/containment-example/CMakeLists.txt b/example/containment-example/CMakeLists.txt new file mode 100644 index 000000000..3f431e502 --- /dev/null +++ b/example/containment-example/CMakeLists.txt @@ -0,0 +1,5 @@ +# SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +# +# SPDX-License-Identifier: GPL-3.0-or-later + +ds_install_package(PACKAGE org.deepin.ds.containment-example) diff --git a/example/containment-example/package/main.qml b/example/containment-example/package/main.qml new file mode 100644 index 000000000..783e0e9cb --- /dev/null +++ b/example/containment-example/package/main.qml @@ -0,0 +1,22 @@ +// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +import QtQuick 2.15 +import QtQuick.Controls 2.4 +import QtQuick.Layouts 1.11 + +import org.deepin.ds 1.0 + +ContainmentItem { + id: root + objectName: "containment item" + RowLayout { + Repeater { + model: Applet.appletItems + delegate: Control { + contentItem: modelData + } + } + } +} \ No newline at end of file diff --git a/example/containment-example/package/metadata.json b/example/containment-example/package/metadata.json new file mode 100644 index 000000000..3507d95c3 --- /dev/null +++ b/example/containment-example/package/metadata.json @@ -0,0 +1,9 @@ +{ + "Plugin": { + "Version": "1.0", + "Id": "org.deepin.ds.containment-example", + "Url": "main.qml", + "Parent": "org.deepin.ds.corona-example", + "ContainmentType": "Containment" + } +} diff --git a/example/corona-example/CMakeLists.txt b/example/corona-example/CMakeLists.txt new file mode 100644 index 000000000..6e24825d9 --- /dev/null +++ b/example/corona-example/CMakeLists.txt @@ -0,0 +1,14 @@ +# SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +# +# SPDX-License-Identifier: GPL-3.0-or-later + +add_library(ds-corona-example SHARED + examplecorona.cpp + examplecorona.h +) + +target_link_libraries(ds-corona-example PRIVATE + dde-shell-frame +) + +ds_install_package(PACKAGE org.deepin.ds.corona-example TARGET ds-corona-example) diff --git a/example/corona-example/examplecorona.cpp b/example/corona-example/examplecorona.cpp new file mode 100644 index 000000000..4b8e30cbe --- /dev/null +++ b/example/corona-example/examplecorona.cpp @@ -0,0 +1,32 @@ +// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "examplecorona.h" + +#include "pluginfactory.h" + + +ExampleCorona::ExampleCorona(QObject *parent) + : DCorona(parent) +{ +} + +ExampleCorona::~ExampleCorona() +{ + +} + +void ExampleCorona::load() +{ + DCorona::load(); +} + +void ExampleCorona::init() +{ + DCorona::init(); +} + +D_APPLET_CLASS(ExampleCorona) + +#include "examplecorona.moc" diff --git a/example/corona-example/examplecorona.h b/example/corona-example/examplecorona.h new file mode 100644 index 000000000..d1a87db02 --- /dev/null +++ b/example/corona-example/examplecorona.h @@ -0,0 +1,22 @@ +// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include "corona.h" + +DS_USE_NAMESPACE + +class Q_DECL_EXPORT ExampleCorona : public DCorona +{ + Q_OBJECT +public: + explicit ExampleCorona(QObject *parent = nullptr); + + virtual ~ExampleCorona(); + + void load() override; + + virtual void init() override; +}; diff --git a/example/corona-example/main.cpp b/example/corona-example/main.cpp new file mode 100644 index 000000000..8ef428959 --- /dev/null +++ b/example/corona-example/main.cpp @@ -0,0 +1,28 @@ +// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "panelview.h" +#include "examplecorona.h" +#include "pluginloader.h" + +#include +#include + +DS_USE_NAMESPACE; + +int main(int argc, char *argv[]) +{ + QGuiApplication a(argc, argv); + + DPluginLoader::instance()->addPackageDir("/home/repo/dde-shell/example"); + + ExampleCorona corona; + corona.load(); + + auto view = corona.view(); + view->resize(600, 400); + view->show(); + + return a.exec(); +} diff --git a/example/corona-example/package/main.qml b/example/corona-example/package/main.qml new file mode 100644 index 000000000..421541102 --- /dev/null +++ b/example/corona-example/package/main.qml @@ -0,0 +1,30 @@ +// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +import QtQuick 2.15 +import QtQuick.Controls 2.4 +import QtQuick.Window 2.15 + +import org.deepin.ds 1.0 +import org.deepin.dtk 1.0 as D + +Window { + id: root + visible: true + width: Screen.width + height: 200 + D.DWindow.enabled: true + Panel.position: Types.TopPositioned + + Control { + anchors.fill: parent + padding: 20 + + contentItem: Applet.appletItems[0] + background: Rectangle { + color: "plum" + opacity: 0.8 + } + } +} diff --git a/example/corona-example/package/metadata.json b/example/corona-example/package/metadata.json new file mode 100644 index 000000000..0925eb7b5 --- /dev/null +++ b/example/corona-example/package/metadata.json @@ -0,0 +1,9 @@ +{ + "Plugin": { + "Version": "1.0", + "Id": "org.deepin.ds.corona-example", + "Url": "main.qml", + "ContainmentType": "Panel", + "Position": "center" + } +} diff --git a/frame/CMakeLists.txt b/frame/CMakeLists.txt new file mode 100644 index 000000000..f5275150f --- /dev/null +++ b/frame/CMakeLists.txt @@ -0,0 +1,73 @@ +# SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +# +# SPDX-License-Identifier: CC0-1.0 + +set(PUBLIC_HEADERS + dsglobal.h + dstypes.h + pluginmetadata.h + pluginloader.h + pluginfactory.h + applet.h + containment.h + corona.h + qmlengine.h +) +add_library(dde-shell-frame SHARED + ${PUBLIC_HEADERS} + private/applet_p.h + private/containment_p.h + private/corona_p.h + private/appletitem_p.h + appletitem.h + containmentitem.h + panelview.h + dstypes.cpp + pluginmetadata.cpp + pluginloader.cpp + pluginfactory.cpp + applet.cpp + containment.cpp + corona.cpp + appletitem.cpp + containmentitem.cpp + panelview.cpp + qmlengine.cpp +) + +set_target_properties(dde-shell-frame PROPERTIES + VERSION ${CMAKE_PROJECT_VERSION} + SOVERSION ${CMAKE_PROJECT_VERSION_MAJOR} + OUTPUT_NAME dde-shell + EXPORT_NAME DDEShell +) +target_link_libraries(dde-shell-frame +PUBLIC + Dtk${DTK_VERSION_MAJOR}::Core + Qt${QT_VERSION_MAJOR}::Core + Qt${QT_VERSION_MAJOR}::Gui + Qt${QT_VERSION_MAJOR}::Quick +) +target_include_directories(dde-shell-frame INTERFACE + $ + $ + $ +) +target_link_directories(dde-shell-frame INTERFACE + $ + $ +) + +target_compile_definitions(dde-shell-frame +INTERFACE + DDE_SHELL_PACKAGE_PATH_SUBPATH="dde-shell" +PRIVATE + DDE_SHELL_QML_INSTALL_DIR="${CMAKE_INSTALL_PREFIX}/${QML_INSTALL_DIR}" + DDE_SHELL_PLUGIN_INSTALL_DIR="${CMAKE_INSTALL_PREFIX}/${DDE_SHELL_PLUGIN_INSTALL_DIR}" +) + +install(FILES ${PUBLIC_HEADERS} DESTINATION "${INCLUDE_INSTALL_DIR}") +install(TARGETS dde-shell-frame EXPORT DDEShellTargets DESTINATION "${LIB_INSTALL_DIR}") +install(EXPORT DDEShellTargets FILE DDEShellTargets.cmake DESTINATION "${CONFIG_INSTALL_DIR}") + +add_subdirectory(plugin) diff --git a/frame/applet.cpp b/frame/applet.cpp new file mode 100644 index 000000000..e67052707 --- /dev/null +++ b/frame/applet.cpp @@ -0,0 +1,60 @@ +// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "applet.h" +#include "private/applet_p.h" + +#include + +DS_BEGIN_NAMESPACE + +DCORE_USE_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(dsLog) + +DApplet::DApplet(QObject *parent) + : DApplet(*new DAppletPrivate(this), parent) +{ +} + +DApplet::DApplet(DAppletPrivate &dd, QObject *parent) + : QObject(parent) + , DObject(dd) +{ + +} + +DApplet::~DApplet() +{ + +} + +void DApplet::setMetaData(const DPluginMetaData &metaData) +{ + D_D(DApplet); + d->m_metaData = metaData; +} + +QString DApplet::pluginId() const +{ + D_DC(DApplet); + return d->m_metaData.pluginId(); +} + +DPluginMetaData DApplet::pluginMetaData() const +{ + D_DC(DApplet); + return d->m_metaData; +} + +void DApplet::init() +{ +} + +void DApplet::load() +{ + +} + +DS_END_NAMESPACE diff --git a/frame/applet.h b/frame/applet.h new file mode 100644 index 000000000..57f887331 --- /dev/null +++ b/frame/applet.h @@ -0,0 +1,40 @@ +// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include "dsglobal.h" +#include "pluginmetadata.h" + +#include +#include + +DS_BEGIN_NAMESPACE +/** + * @brief 插件项,单个插件实例 + */ +class DAppletPrivate; +class Q_DECL_EXPORT DApplet : public QObject, public DTK_CORE_NAMESPACE::DObject +{ + Q_OBJECT + Q_PROPERTY(QString pluginId READ pluginId CONSTANT FINAL) + D_DECLARE_PRIVATE(DApplet) +public: + DApplet(QObject *parent = nullptr); + virtual ~DApplet(); + + void setMetaData(const DPluginMetaData &metaData); + QString pluginId() const; + + DPluginMetaData pluginMetaData() const; + + virtual void init(); + + virtual void load(); + +protected: + DApplet(DAppletPrivate &dd, QObject *parent = nullptr); +}; + +DS_END_NAMESPACE diff --git a/frame/appletitem.cpp b/frame/appletitem.cpp new file mode 100644 index 000000000..93f379929 --- /dev/null +++ b/frame/appletitem.cpp @@ -0,0 +1,84 @@ +// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "appletitem.h" +#include "private/appletitem_p.h" +#include "applet.h" +#include "qmlengine.h" + +#include +#include +#include +#include + +DS_BEGIN_NAMESPACE +DCORE_USE_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(dsLog) + +static QMap g_appletItems; + +DAppletItem::DAppletItem(QQuickItem *parent) + : QQuickItem(parent) + , DObject(*new DAppletItemPrivate(this)) +{ +} + +DAppletItem::~DAppletItem() +{ +} + +DApplet *DAppletItem::applet() const +{ + D_DC(DAppletItem); + return d->m_applet; +} + +DAppletItem *DAppletItem::itemForApplet(DApplet *applet) +{ + auto it = g_appletItems.constFind(applet); + if (it != g_appletItems.constEnd()) + return it.value(); + + QScopedPointer engine(new DQmlEngine(applet, applet)); + + auto rootObject = engine->beginCreate(); + if (!rootObject) { + return nullptr; + } + + auto item = qobject_cast(rootObject); + if (!item) { + rootObject->deleteLater(); + return nullptr; + } + + item->d_func()->m_applet = applet; + item->d_func()->m_engine = engine.take(); + g_appletItems[applet] = item; + + item->d_func()->m_engine->completeCreate(); + + return item; +} + +DApplet *DAppletItem::qmlAttachedProperties(QObject *object) +{ + QQuickItem *item = qobject_cast(object); + while (item) { + if (auto appletItem = qobject_cast(item)) { + return appletItem->applet(); + } + item = item->parentItem(); + } + if (!item) { + item = qobject_cast(object); + if(auto applet = item->window()->property("_ds_window_applet").value()) { + return applet; + } + } + return nullptr; +} + +DS_END_NAMESPACE diff --git a/frame/appletitem.h b/frame/appletitem.h new file mode 100644 index 000000000..9b2ea82de --- /dev/null +++ b/frame/appletitem.h @@ -0,0 +1,36 @@ +// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include "dsglobal.h" + +#include +#include + +DS_BEGIN_NAMESPACE + +class DApplet; +class DAppletItemPrivate; +/** + * @brief UI插件实例项 + */ +class Q_DECL_EXPORT DAppletItem : public QQuickItem, public DTK_CORE_NAMESPACE::DObject +{ + Q_OBJECT + D_DECLARE_PRIVATE(DAppletItem) +public: + explicit DAppletItem(QQuickItem *parent = nullptr); + virtual ~DAppletItem(); + + DApplet *applet() const; + + static DAppletItem *itemForApplet(DApplet *applet); + + static DApplet *qmlAttachedProperties(QObject *object); +}; + +DS_END_NAMESPACE + +QML_DECLARE_TYPEINFO(DS_NAMESPACE::DAppletItem, QML_HAS_ATTACHED_PROPERTIES) diff --git a/frame/containment.cpp b/frame/containment.cpp new file mode 100644 index 000000000..d6124a20e --- /dev/null +++ b/frame/containment.cpp @@ -0,0 +1,89 @@ +// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "containment.h" +#include "private/containment_p.h" + +#include "pluginloader.h" +#include "pluginmetadata.h" +#include "appletitem.h" + +#include + +DS_BEGIN_NAMESPACE +DCORE_USE_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(dsLog) + +DContainment::DContainment(QObject *parent) + : DContainment(*new DContainmentPrivate(this), parent) +{ +} + +DContainment::DContainment(DContainmentPrivate &dd, QObject *parent) + : DApplet(dd, parent) +{ + +} + +DContainment::~DContainment() +{ + +} + +DApplet *DContainment::createApplet(const QString &pluginId) +{ + D_D(DContainment); + auto applet = DPluginLoader::instance()->loadApplet(pluginId); + if (applet) { + d->m_applets.append(applet); + } + return applet; +} + +QList DContainment::applets() const +{ + D_DC(DContainment); + return d->m_applets; +} + +QList DContainment::appletItems() +{ + D_D(DContainment); + + return d->m_appletItems; +} + +void DContainment::load() +{ + const auto children = DPluginLoader::instance()->childrenPlugin(pluginId()); + for (auto item : children) { + const QString id = item.pluginId(); + auto applet = createApplet(id); + + if (applet) { + applet->load(); + } + } + DApplet::load(); +} + +void DContainment::init() +{ + D_D(DContainment); + + for (auto applet : applets()) { + auto appletItem = DAppletItem::itemForApplet(applet); + if (!appletItem || d->m_appletItems.contains(appletItem)) + continue; + d->m_appletItems << appletItem; + + applet->init(); + } + DApplet::init(); + + Q_EMIT appletItemsChanged(); +} + +DS_END_NAMESPACE diff --git a/frame/containment.h b/frame/containment.h new file mode 100644 index 000000000..ea1f8f7a0 --- /dev/null +++ b/frame/containment.h @@ -0,0 +1,43 @@ +// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include "applet.h" + +#include +#include + +DS_BEGIN_NAMESPACE + +/** + * @brief 容器插件 + */ +class DContainmentPrivate; +class Q_DECL_EXPORT DContainment : public DApplet +{ + Q_OBJECT + Q_PROPERTY(QList appletItems READ appletItems NOTIFY appletItemsChanged) + D_DECLARE_PRIVATE(DContainment) +public: + explicit DContainment(QObject *parent = nullptr); + virtual ~DContainment(); + + DApplet *createApplet(const QString &pluginId); + + QList applets() const; + QList appletItems(); + + void load() override; + + void init() override; + +protected: + DContainment(DContainmentPrivate &dd, QObject *parent = nullptr); + +Q_SIGNALS: + void appletItemsChanged(); +}; + +DS_END_NAMESPACE diff --git a/frame/containmentitem.cpp b/frame/containmentitem.cpp new file mode 100644 index 000000000..9e35c16f9 --- /dev/null +++ b/frame/containmentitem.cpp @@ -0,0 +1,28 @@ +// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "containmentitem.h" + +#include +#include + +DS_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(dsLog) + +DContainmentItem::DContainmentItem(QQuickItem *parent) + : DAppletItem(parent) +{ +} + +DContainmentItem::~DContainmentItem() +{ +} + +DContainment *DContainmentItem::qmlAttachedProperties(QObject *object) +{ + return qobject_cast(DAppletItem::qmlAttachedProperties(object)); +} + +DS_END_NAMESPACE diff --git a/frame/containmentitem.h b/frame/containmentitem.h new file mode 100644 index 000000000..976d47d79 --- /dev/null +++ b/frame/containmentitem.h @@ -0,0 +1,31 @@ +// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include "dsglobal.h" +#include "appletitem.h" +#include "containment.h" + +DS_BEGIN_NAMESPACE + +class DContainment; +class DContainmentItemPrivate; +/** + * @brief UI插件实例项 + */ +class Q_DECL_EXPORT DContainmentItem : public DAppletItem +{ + Q_OBJECT + D_DECLARE_PRIVATE(DContainmentItem) +public: + explicit DContainmentItem(QQuickItem *parent = nullptr); + virtual ~DContainmentItem(); + + static DContainment *qmlAttachedProperties(QObject *object); +}; + +DS_END_NAMESPACE + +QML_DECLARE_TYPEINFO(DS_NAMESPACE::DContainmentItem, QML_HAS_ATTACHED_PROPERTIES) diff --git a/frame/corona.cpp b/frame/corona.cpp new file mode 100644 index 000000000..5cda79613 --- /dev/null +++ b/frame/corona.cpp @@ -0,0 +1,87 @@ +// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "corona.h" +#include "private/corona_p.h" + +#include "dstypes.h" +#include "pluginloader.h" +#include "panelview.h" +#include "qmlengine.h" + +#include + +DS_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(dsLog) + +static Types::Position typePosition(const QString &p) +{ + const QMap mapping { + {"left", Types::LeftPositioned}, + {"right", Types::RightPositioned}, + {"center", Types::CenterPositioned}, + {"top", Types::TopPositioned}, + {"bottom", Types::BottomPositioned} + }; + if (mapping.contains(p)) { + return mapping.value(p); + } + return {}; +} + +DCorona::DCorona(QObject *parent) + : DContainment(*new DCoronaPrivate(this), parent) +{ +} + +DCorona::~DCorona() +{ + +} + +void DCoronaPrivate::createWindow() +{ + D_Q(DCorona); +} + +QQuickWindow *DCorona::window() const +{ + D_DC(DCorona); + return d->m_window; +} + +void DCorona::load() +{ + D_D(DCorona); + DContainment::load(); +} + +void DCorona::init() +{ + D_D(DCorona); + + auto applet = this; + + DQmlEngine *engine = new DQmlEngine(applet, applet); + + auto rootObject = engine->beginCreate(); + + auto window = qobject_cast(rootObject); + if (window) { + d->m_window = window; + d->m_window->setProperty("_ds_window_applet", QVariant::fromValue(applet)); + + if (auto panel = qobject_cast(qmlAttachedPropertiesObject(window))) { + const QString position = applet->pluginMetaData().value("Position").toString(); + panel->setPosition(typePosition(position)); + } + } + + DContainment::init(); + + engine->completeCreate(); +} + +DS_END_NAMESPACE diff --git a/frame/corona.h b/frame/corona.h new file mode 100644 index 000000000..c27504d8c --- /dev/null +++ b/frame/corona.h @@ -0,0 +1,35 @@ +// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include "dsglobal.h" +#include "containment.h" + +#include + +DS_BEGIN_NAMESPACE + +/** + * @brief 插件集 + */ +class DCoronaPrivate; +class Q_DECL_EXPORT DCorona : public DContainment +{ + Q_OBJECT + D_DECLARE_PRIVATE(DCorona) +public: + explicit DCorona(QObject *parent = nullptr); + virtual ~DCorona(); + + QQuickWindow *window() const; + + // 加载插件 + virtual void load() override; + + // 初始化 + virtual void init() override; +}; + +DS_END_NAMESPACE diff --git a/frame/dsglobal.h b/frame/dsglobal.h new file mode 100644 index 000000000..3b51881ec --- /dev/null +++ b/frame/dsglobal.h @@ -0,0 +1,13 @@ +// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include + +#define DS_NAMESPACE ds + +#define DS_BEGIN_NAMESPACE namespace DS_NAMESPACE { +#define DS_END_NAMESPACE } +#define DS_USE_NAMESPACE using namespace DS_NAMESPACE; diff --git a/frame/dstypes.cpp b/frame/dstypes.cpp new file mode 100644 index 000000000..33ec5bed8 --- /dev/null +++ b/frame/dstypes.cpp @@ -0,0 +1,17 @@ +// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "dstypes.h" + +#include + +DS_BEGIN_NAMESPACE + +Types::Types(QObject *parent) + : QObject(parent) +{ + +} + +DS_END_NAMESPACE \ No newline at end of file diff --git a/frame/dstypes.h b/frame/dstypes.h new file mode 100644 index 000000000..0b0fa76b1 --- /dev/null +++ b/frame/dstypes.h @@ -0,0 +1,40 @@ +// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include "dsglobal.h" +#include + +DS_BEGIN_NAMESPACE + +class Types : public QObject +{ + Q_OBJECT +public: + Types(QObject *parent = nullptr); + enum Location { + Floating = 0, /**< Free floating. Neither geometry or z-ordering + is described precisely by this value. */ + Desktop, /**< On the planar desktop layer, extending across + the full screen from edge to edge */ + FullScreen, /**< Full screen */ + TopEdge, /**< Along the top of the screen*/ + BottomEdge, /**< Along the bottom of the screen*/ + LeftEdge, /**< Along the left side of the screen */ + RightEdge, /**< Along the right side of the screen */ + }; + Q_ENUM(Location) + + enum Position { + LeftPositioned, /**< Positioned left */ + RightPositioned, /**< Positioned right */ + TopPositioned, /**< Positioned top */ + BottomPositioned, /**< Positioned bottom */ + CenterPositioned, /**< Positioned in the center */ + }; + Q_ENUM(Position) +}; + +DS_END_NAMESPACE \ No newline at end of file diff --git a/frame/panelview.cpp b/frame/panelview.cpp new file mode 100644 index 000000000..a5bc71308 --- /dev/null +++ b/frame/panelview.cpp @@ -0,0 +1,102 @@ +// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "panelview.h" + +#include +#include +#include + +DS_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(dsLog) + +class DPanelViewPrivate +{ +public: + DPanelViewPrivate() + { + } + Types::Location m_location; + Types::Position m_position; +}; + +DPanelView::DPanelView(QQuickWindow *window) + : QObject(window) + , d(new DPanelViewPrivate()) +{ +} + +DPanelView::~DPanelView() +{ + +} + +QQuickWindow *DPanelView::window() const +{ + return qobject_cast(parent()); +} + +DPanelView *DPanelView::qmlAttachedProperties(QObject *object) +{ + QQuickWindow *window = qobject_cast(object); + if (window) { + return new DPanelView(window); + } + + return nullptr; +} + +void DPanelView::positionPanel() +{ + QRect rect = window()->geometry(); + auto screen = window()->screen(); + switch(d->m_position) { + case Types::CenterPositioned: { + rect.moveCenter(screen->geometry().center()); + } break; + case Types::TopPositioned: { + rect.moveTop(screen->geometry().top()); + } break; + case Types::BottomPositioned: { + rect.moveBottom(screen->geometry().bottom()); + } break; + default: + break; + } + + if (rect != window()->geometry()) { + window()->setGeometry(rect); + } +} + +Types::Location DPanelView::location() const +{ + return d->m_location; +} + +void DPanelView::setLocation(const Types::Location &newLocation) +{ + if (d->m_location == newLocation) + return; + d->m_location = newLocation; + emit locationChanged(); +} + +Types::Position DPanelView::position() const +{ + return d->m_position; +} + +void DPanelView::setPosition(const Types::Position &newPosition) +{ + if (d->m_position == newPosition) + return; + d->m_position = newPosition; + positionPanel(); + emit positionChanged(); +} + + +DS_END_NAMESPACE diff --git a/frame/panelview.h b/frame/panelview.h new file mode 100644 index 000000000..b16852795 --- /dev/null +++ b/frame/panelview.h @@ -0,0 +1,53 @@ +// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include "dsglobal.h" +#include "dstypes.h" + +#include + +DS_BEGIN_NAMESPACE + +class DPluginMetaData; +/** + * @brief 插件项 + */ +class DPanelViewPrivate; +class Q_DECL_EXPORT DPanelView : public QObject +{ + Q_OBJECT + Q_PROPERTY(QQuickWindow* window READ window FINAL) + Q_PROPERTY(DS_NAMESPACE::Types::Location location READ location WRITE setLocation NOTIFY locationChanged FINAL) + Q_PROPERTY(DS_NAMESPACE::Types::Position position READ position WRITE setPosition NOTIFY positionChanged FINAL) +public: + DPanelView(QQuickWindow *window = nullptr); + virtual ~DPanelView(); + + QQuickWindow *window() const; + + Types::Location location() const; + void setLocation(const Types::Location &newLocation); + + static DPanelView *qmlAttachedProperties(QObject *object); + + Types::Position position() const; + void setPosition(const Types::Position &newPosition); + +Q_SIGNALS: + void locationChanged(); + + void positionChanged(); + +private: + void positionPanel(); + +private: + DPanelViewPrivate *d = nullptr; +}; + +DS_END_NAMESPACE + +QML_DECLARE_TYPEINFO(DS_NAMESPACE::DPanelView, QML_HAS_ATTACHED_PROPERTIES) diff --git a/frame/plugin/CMakeLists.txt b/frame/plugin/CMakeLists.txt new file mode 100644 index 000000000..f4344f1e6 --- /dev/null +++ b/frame/plugin/CMakeLists.txt @@ -0,0 +1,29 @@ +# SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +# +# SPDX-License-Identifier: CC0-1.0 + +set(URI "org.deepin.ds") +add_library(dde-shell-plugin SHARED + qmlplugin.h + qmlplugin.cpp + qmldir +) + +target_link_libraries(dde-shell-plugin +PUBLIC + dde-shell-frame +) + +string(REPLACE "." "/" URI_PATH ${URI}) +set_target_properties(dde-shell-plugin PROPERTIES + LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/plugins/${URI_PATH}" + OUTPUT_NAME dde-shell-plugin +) +set(QML_IMPORT_PATH "${PROJECT_BINARY_DIR}/plugins/${URI_PATH}" CACHE STRING "Qt Creator extra qml import paths") +add_custom_command(TARGET dde-shell-plugin +POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_CURRENT_SOURCE_DIR}/qmldir" "${PROJECT_BINARY_DIR}/plugins/${URI_PATH}" #out-file +) + +install(TARGETS dde-shell-plugin EXPORT DDEShellTargets DESTINATION "${QML_INSTALL_DIR}/${URI_PATH}") +install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/qmldir DESTINATION "${QML_INSTALL_DIR}/${URI_PATH}/") diff --git a/frame/plugin/qmldir b/frame/plugin/qmldir new file mode 100644 index 000000000..87607373c --- /dev/null +++ b/frame/plugin/qmldir @@ -0,0 +1,2 @@ +module org.deepin.ds +plugin dde-shell-plugin diff --git a/frame/plugin/qmlplugin.cpp b/frame/plugin/qmlplugin.cpp new file mode 100644 index 000000000..9c8358cf8 --- /dev/null +++ b/frame/plugin/qmlplugin.cpp @@ -0,0 +1,33 @@ +// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "qmlplugin.h" +#include "applet.h" +#include "appletitem.h" +#include "containmentitem.h" +#include "panelview.h" + +DS_BEGIN_NAMESPACE + +void QmlpluginPlugin::registerTypes(const char *uri) +{ + // @uri org.deepin.ds + qmlRegisterModule(uri, 1, 0); + + qmlRegisterUncreatableType(uri, 1, 0, "Types", "Types"); + + qmlRegisterAnonymousType(uri, 1); + qmlRegisterType(uri, 1, 0, "AppletItem"); + qmlRegisterUncreatableType(uri, 1, 0, "Applet", "Applet Attached"); + qmlRegisterType(uri, 1, 0, "ContainmentItem"); + qmlRegisterUncreatableType(uri, 1, 0, "Containment", "Containment Attached"); + qmlRegisterUncreatableType(uri, 1, 0, "Panel", "Panel Attached"); +} + +void QmlpluginPlugin::initializeEngine(QQmlEngine *engine, const char *uri) +{ + QQmlExtensionPlugin::initializeEngine(engine, uri); +} + +DS_END_NAMESPACE diff --git a/frame/plugin/qmlplugin.h b/frame/plugin/qmlplugin.h new file mode 100644 index 000000000..1d18af1be --- /dev/null +++ b/frame/plugin/qmlplugin.h @@ -0,0 +1,21 @@ +// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include "dsglobal.h" + +#include + +DS_BEGIN_NAMESPACE +class QmlpluginPlugin : public QQmlExtensionPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) + +public: + void registerTypes(const char *uri) override; + void initializeEngine(QQmlEngine *engine, const char *uri) override; +}; +DS_END_NAMESPACE \ No newline at end of file diff --git a/frame/pluginfactory.cpp b/frame/pluginfactory.cpp new file mode 100644 index 000000000..995a81808 --- /dev/null +++ b/frame/pluginfactory.cpp @@ -0,0 +1,48 @@ +// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "pluginfactory.h" + +#include +#include + +DS_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(dsLog) + +static QMap g_appletFactory; + +void DAppletFactory::registerInstance(CreateAppletFunction func) +{ + const QString key = metaObject()->className(); + if (g_appletFactory.contains(key)) { + qCWarning(dsLog()) << "The applet factory has registed" << key; + return; + } + g_appletFactory[key] = func; + qCDebug(dsLog()) << "Registed the applet factory" << key; +} + +DAppletFactory::DAppletFactory(QObject *parent) + : QObject(parent) +{ + +} + +DAppletFactory::~DAppletFactory() +{ + +} + +DApplet *DAppletFactory::create(QObject *parent) +{ + const QString key = metaObject()->className(); + if (g_appletFactory.contains(key)) { + DAppletFactory::CreateAppletFunction func = g_appletFactory.value(key); + return func(parent); + } + return nullptr; +} + +DS_END_NAMESPACE diff --git a/frame/pluginfactory.h b/frame/pluginfactory.h new file mode 100644 index 000000000..3c691d11b --- /dev/null +++ b/frame/pluginfactory.h @@ -0,0 +1,62 @@ +// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include "dsglobal.h" + +#include + +DS_BEGIN_NAMESPACE + +class DApplet; + +#define DAppletFactory_iid "org.deepin.ds.applet-factory" + +/** + * @brief 插件注册 + */ +class DAppletFactoryPrivate; +class Q_DECL_EXPORT DAppletFactory : public QObject +{ + Q_OBJECT +public: + explicit DAppletFactory(QObject *parent = nullptr); + ~DAppletFactory(); + + using CreateAppletFunction = std::function; + void registerInstance(CreateAppletFunction func); + + template + static inline T *registerApplet(QObject *parent) + { + return new T(parent); + } + + virtual DApplet *create(QObject *parent = nullptr); +private: + DAppletFactoryPrivate *d = nullptr; +}; + +DS_END_NAMESPACE + +Q_DECLARE_INTERFACE(DS_NAMESPACE::DAppletFactory, DAppletFactory_iid) + +#define D_APPLET_CLASS(classname) \ + \ +namespace { \ + \ +class Q_DECL_EXPORT classname##AppletFactory : public DS_NAMESPACE::DAppletFactory \ +{ \ + Q_OBJECT \ + Q_PLUGIN_METADATA(IID DAppletFactory_iid) \ + Q_INTERFACES(DS_NAMESPACE::DAppletFactory) \ + public: \ + classname##AppletFactory() \ + : DS_NAMESPACE::DAppletFactory() \ + { \ + registerInstance(registerApplet); \ + } \ +}; \ +} diff --git a/frame/pluginloader.cpp b/frame/pluginloader.cpp new file mode 100644 index 000000000..fd560b73a --- /dev/null +++ b/frame/pluginloader.cpp @@ -0,0 +1,253 @@ +// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "pluginloader.h" + +#include "applet.h" +#include "containment.h" +#include "pluginmetadata.h" +#include "pluginfactory.h" + +#include +#include +#include +#include +#include +#include +#include + +DS_BEGIN_NAMESPACE; + +DCORE_USE_NAMESPACE + +static const QString MetaDataFileName{"metadata.json"}; + +Q_DECLARE_LOGGING_CATEGORY(dsLog) + +class DPluginLoaderPrivate : public DObjectPrivate +{ +public: + explicit DPluginLoaderPrivate(DPluginLoader *qq) + : DObjectPrivate(qq) + { + m_pluginDirs = buildinPackagePaths(); + } + void init() + { + D_Q(DPluginLoader); + + for (auto item : buildinPluginPaths()) { + q->addPluginDir(item); + } + + const QString rootDir(QCoreApplication::applicationDirPath()); + + for (auto item : m_pluginDirs) { + const QDirIterator::IteratorFlags flags = QDirIterator::Subdirectories; + const QStringList nameFilters = {MetaDataFileName}; + + QDirIterator it(item, nameFilters, QDir::Files, flags); + QSet dirs; + while (it.hasNext()) { + it.next(); + + const QString dir = it.fileInfo().absoluteDir().path(); + if (dirs.contains(dir)) { + continue; + } + dirs << dir; + + const QString metadataPath = it.fileInfo().absoluteFilePath(); + DPluginMetaData info = DPluginMetaData::fromJsonFile(metadataPath); + if (!info.isValid()) + continue; + + if (m_plugins.contains(info.pluginId())) + continue; + + m_plugins[info.pluginId()] = info; + } + } + } + + QStringList buildinPackagePaths() + { + QStringList result; + // 'DDE_SHELL_PACKAGE_PATH' directory. + const auto dtkPluginPath = qgetenv("DDE_SHELL_PACKAGE_PATH"); + if (!dtkPluginPath.isEmpty()) + result.append(dtkPluginPath); + + result << QCoreApplication::applicationDirPath(); + result << QCoreApplication::applicationDirPath(); + result << QCoreApplication::applicationDirPath() + "/../packages"; + + for (auto item : QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation)) { + result << item + "/dde-shell"; + } + qCDebug(dsLog()) << "Buildin package paths" << result; + + return result; + } + + QStringList buildinPluginPaths() + { + QStringList result; + // 'DDE_SHELL_PACKAGE_PATH' directory. + const auto dtkPluginPath = qgetenv("DDE_SHELL_PLUGIN_PATH"); + if (!dtkPluginPath.isEmpty()) + result.append(dtkPluginPath); + + result << QCoreApplication::applicationDirPath() + "/../plugins"; + result << DDE_SHELL_PLUGIN_INSTALL_DIR; + + qCDebug(dsLog()) << "Buildin plugin paths" << result; + return result; + } + + DAppletFactory *appletFactory(const DPluginMetaData &data) + { + DAppletFactory *factory = nullptr; + const QString fileName = data.pluginId(); + QPluginLoader loader(fileName); + loader.load(); + if (!loader.isLoaded()) { + return factory; + } + + const auto &meta = loader.metaData(); + + do { + const auto iid = meta["IID"].toString(); + if (iid.isEmpty()) + break; + + if (iid != QString(qobject_interface_iid())) + break; + + if (!loader.instance()) { + qWarning(dsLog) << "Load the plugin failed." << loader.errorString(); + break; + } + factory = qobject_cast(loader.instance()); + if (!factory) { + qWarning(dsLog) << "The plugin isn't a DAppletFactory." << fileName; + break; + } + } while (false); + + return factory; + } + + DPluginMetaData pluginMetaData(const QString &pluginId) const + { + const auto it = m_plugins.constFind(pluginId); + if (it == m_plugins.constEnd()) + return {}; + return it.value(); + } + + QStringList m_pluginDirs; + QMap m_plugins; + + D_DECLARE_PUBLIC(DPluginLoader) +}; + +DPluginLoader::DPluginLoader() + : DObject(*new DPluginLoaderPrivate(this)) +{ +} + +DPluginLoader::~DPluginLoader() +{ + +} + +DPluginLoader *DPluginLoader::instance() +{ + static DPluginLoader *g_instance = nullptr; + if (!g_instance) { + g_instance = new DPluginLoader(); + g_instance->d_func()->init(); + } + return g_instance; +} + +QList DPluginLoader::plugins() const +{ + D_DC(DPluginLoader); + return d->m_plugins.values(); +} + +void DPluginLoader::addPackageDir(const QString &dir) +{ + D_D(DPluginLoader); + d->m_pluginDirs.prepend(dir); + d->init(); +} + +void DPluginLoader::addPluginDir(const QString &dir) +{ + if (QCoreApplication::libraryPaths().contains(dir)) + return; + QCoreApplication::addLibraryPath(dir); +} + +DApplet *DPluginLoader::loadApplet(const QString &pluginId) +{ + D_D(DPluginLoader); + DPluginMetaData metaData = d->pluginMetaData(pluginId); + if (!metaData.isValid()) + return nullptr; + + DApplet *applet = nullptr; + if (auto factory = d->appletFactory(metaData)) { + qCDebug(dsLog()) << "Loading applet by factory" << pluginId; + applet = factory->create(); + } + if (!applet) { + if (metaData.value("ContainmentType").isValid()) { + applet = new DContainment(); + } + } + + if (!applet) { + applet = new DApplet(); + } + if (applet) { + applet->setMetaData(metaData); + } + return applet; +} + +QList DPluginLoader::childrenPlugin(const QString &pluginId) const +{ + D_DC(DPluginLoader); + DPluginMetaData metaData = d->pluginMetaData(pluginId); + if (!metaData.isValid()) + return {}; + + const DPluginMetaData target(metaData); + QList result; + for (auto md : d->m_plugins.values()) { + const QString parentId(md.value("Parent").toString()); + if (parentId == target.pluginId()) { + result << md; + } + } + return result; +} + +DPluginMetaData DPluginLoader::parentPlugin(const QString &pluginId) const +{ + D_DC(DPluginLoader); + DPluginMetaData metaData = d->pluginMetaData(pluginId); + if (!metaData.isValid()) + return {}; + + const QString parentId(metaData.value("Parent").toString()); + return d->pluginMetaData(parentId); +} + +DS_END_NAMESPACE diff --git a/frame/pluginloader.h b/frame/pluginloader.h new file mode 100644 index 000000000..616de1191 --- /dev/null +++ b/frame/pluginloader.h @@ -0,0 +1,39 @@ +// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include "dsglobal.h" +#include "pluginmetadata.h" +#include +#include + +DS_BEGIN_NAMESPACE + +class DApplet; + +/** + * @brief 插件加载,创建 + */ +class DPluginLoaderPrivate; +class Q_DECL_EXPORT DPluginLoader : public QObject, public DTK_CORE_NAMESPACE::DObject +{ + Q_OBJECT + D_DECLARE_PRIVATE(DPluginLoader) +public: + DPluginLoader(); + virtual ~DPluginLoader(); + + static DPluginLoader *instance(); + QList plugins() const; + void addPackageDir(const QString &dir); + void addPluginDir(const QString &dir); + + DApplet *loadApplet(const QString &pluginId); + + QList childrenPlugin(const QString &pluginId) const; + DPluginMetaData parentPlugin(const QString &pluginId) const; +}; + +DS_END_NAMESPACE diff --git a/frame/pluginmetadata.cpp b/frame/pluginmetadata.cpp new file mode 100644 index 000000000..ee8d47809 --- /dev/null +++ b/frame/pluginmetadata.cpp @@ -0,0 +1,106 @@ +// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "pluginmetadata.h" + +#include +#include +#include +#include +#include +#include + +DS_BEGIN_NAMESPACE + +Q_LOGGING_CATEGORY(dsLog, "dde.shell") + +class DPluginMetaDataPrivate : public QSharedData +{ +public: + QVariantMap rootObject() const + { + return m_metaData["Plugin"].toMap(); + } + QString m_pluginId; + QVariantMap m_metaData; + QString m_pluginDir; +}; + +DPluginMetaData::DPluginMetaData() + : d(new DPluginMetaDataPrivate()) +{ +} + +DPluginMetaData::DPluginMetaData(const DPluginMetaData &other) + : d(other.d) +{ +} + +DPluginMetaData &DPluginMetaData::operator=(const DPluginMetaData &other) +{ + d = other.d; + return *this; +} + +bool DPluginMetaData::operator==(const DPluginMetaData &other) const +{ + return d->m_pluginId == other.pluginId(); +} + +DPluginMetaData::~DPluginMetaData() +{ + +} + +bool DPluginMetaData::isValid() const +{ + return !d->m_pluginId.isEmpty(); +} + +QVariant DPluginMetaData::value(const QString &key, const QVariant &defaultValue) const +{ + if (!isValid()) + return defaultValue; + + auto root = d->rootObject(); + if (!root.contains(key)) + return defaultValue; + + return root.value(key); +} + +QString DPluginMetaData::pluginId() const +{ + return d->m_pluginId; +} + +QString DPluginMetaData::pluginDir() const +{ + return d->m_pluginDir; +} + +DPluginMetaData DPluginMetaData::fromJsonFile(const QString &file) +{ + QFile f(file); + if (!f.open(QIODevice::ReadOnly)) { + qCWarning(dsLog) << "Couldn't open" << file; + return DPluginMetaData(); + } + QJsonParseError error; + const QJsonObject metaData = QJsonDocument::fromJson(f.readAll(), &error).object(); + if (error.error) { + qCWarning(dsLog) << "error parsing" << file << error.errorString(); + } + + DPluginMetaData result; + result.d->m_metaData = metaData.toVariantMap(); + result.d->m_pluginDir = QFileInfo(f).absoluteDir().path(); + auto root = result.d->rootObject(); + if (root.contains("Id")) { + result.d->m_pluginId = root["Id"].toString(); + } + return result; +} + +DS_END_NAMESPACE diff --git a/frame/pluginmetadata.h b/frame/pluginmetadata.h new file mode 100644 index 000000000..30475c7be --- /dev/null +++ b/frame/pluginmetadata.h @@ -0,0 +1,38 @@ +// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include "dsglobal.h" +#include +#include + +DS_BEGIN_NAMESPACE + +/** + * @brief 插件元数据 + */ +class DPluginMetaDataPrivate; +class Q_DECL_EXPORT DPluginMetaData : public QObject +{ + Q_OBJECT +public: + DPluginMetaData(); + DPluginMetaData(const DPluginMetaData &other); + DPluginMetaData &operator=(const DPluginMetaData &other); + bool operator==(const DPluginMetaData &other) const; + virtual ~DPluginMetaData(); + bool isValid() const; + QVariant value(const QString &key, const QVariant &defaultValue = QVariant()) const; + + QString pluginId() const; + QString pluginDir() const; + + static DPluginMetaData fromJsonFile(const QString &file); + +private: + QExplicitlySharedDataPointer d; +}; + +DS_END_NAMESPACE \ No newline at end of file diff --git a/frame/private/applet_p.h b/frame/private/applet_p.h new file mode 100644 index 000000000..8d1f71347 --- /dev/null +++ b/frame/private/applet_p.h @@ -0,0 +1,29 @@ +// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include "applet.h" + +#include +#include + +DS_BEGIN_NAMESPACE +/** + * @brief 插件项,单个插件实例 + */ +class Q_DECL_EXPORT DAppletPrivate : public DTK_CORE_NAMESPACE::DObjectPrivate +{ +public: + DAppletPrivate(DApplet *qq ) + : DTK_CORE_NAMESPACE::DObjectPrivate(qq) + { + } + + DPluginMetaData m_metaData; + + D_DECLARE_PUBLIC(DApplet); +}; + +DS_END_NAMESPACE diff --git a/frame/private/appletitem_p.h b/frame/private/appletitem_p.h new file mode 100644 index 000000000..ad8074ecb --- /dev/null +++ b/frame/private/appletitem_p.h @@ -0,0 +1,27 @@ +// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include "appletitem.h" + +#include "qmlengine.h" +#include +#include + +DS_BEGIN_NAMESPACE + +class DAppletItemPrivate : public DTK_CORE_NAMESPACE::DObjectPrivate +{ +public: + explicit DAppletItemPrivate(DAppletItem *qq) + : DTK_CORE_NAMESPACE::DObjectPrivate(qq) + { + } + + DApplet *m_applet = nullptr; + DQmlEngine *m_engine = nullptr; +}; + +DS_END_NAMESPACE diff --git a/frame/private/containment_p.h b/frame/private/containment_p.h new file mode 100644 index 000000000..1cdf97aeb --- /dev/null +++ b/frame/private/containment_p.h @@ -0,0 +1,31 @@ +// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include "applet_p.h" +#include "containment.h" + +#include +#include + +DS_BEGIN_NAMESPACE +/** + * @brief 插件项 + */ +class DContainmentPrivate : public DAppletPrivate +{ +public: + explicit DContainmentPrivate(DContainment *qq) + : DAppletPrivate(qq) + { + + } + QList m_applets; + QList m_appletItems; + + D_DECLARE_PUBLIC(DContainment) +}; + +DS_END_NAMESPACE \ No newline at end of file diff --git a/frame/private/corona_p.h b/frame/private/corona_p.h new file mode 100644 index 000000000..805e8381f --- /dev/null +++ b/frame/private/corona_p.h @@ -0,0 +1,33 @@ +// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include "containment_p.h" +#include "corona.h" + +#include +#include + +DS_BEGIN_NAMESPACE +/** + * @brief 插件项 + */ +class DCoronaPrivate : public DContainmentPrivate +{ +public: + explicit DCoronaPrivate(DCorona *qq) + : DContainmentPrivate(qq) + { + + } + + void createWindow(); + + QQuickWindow *m_window = nullptr; + + D_DECLARE_PUBLIC(DCorona) +}; + +DS_END_NAMESPACE \ No newline at end of file diff --git a/frame/qmlengine.cpp b/frame/qmlengine.cpp new file mode 100644 index 000000000..28aa5da4d --- /dev/null +++ b/frame/qmlengine.cpp @@ -0,0 +1,122 @@ +// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "qmlengine.h" +#include "applet.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +DS_BEGIN_NAMESPACE +DCORE_USE_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(dsLog) + +class DQmlEnginePrivate : public DObjectPrivate +{ +public: + explicit DQmlEnginePrivate(DQmlEngine *qq) + : DObjectPrivate(qq) + { + + } + DApplet *m_applet = nullptr; + QQmlContext *m_context = nullptr; + QQmlComponent *m_component = nullptr; + QObject *m_rootObject = nullptr; + QQmlEngine *engine() + { + static QQmlEngine *s_engine = nullptr; + if (!s_engine) { + s_engine = new QQmlEngine(); + const QString rootDir = QCoreApplication::applicationDirPath(); + s_engine->addImportPath(rootDir + "/../plugins"); + s_engine->addImportPath(DDE_SHELL_QML_INSTALL_DIR); + qCDebug(dsLog()) << "Engine importPaths" << s_engine->importPathList(); + } + return s_engine; + } + QString appletUrl() const + { + if (!m_applet) + return QString(); + + auto url = m_applet->pluginMetaData().value("Url").toString(); + if (url.isEmpty()) + return QString(); + + return QDir(m_applet->pluginMetaData().pluginDir()).absoluteFilePath(url); + } +}; + +DQmlEngine::DQmlEngine(QObject *parent) + : DQmlEngine(nullptr, parent) +{ + +} + +DQmlEngine::DQmlEngine(DApplet *applet, QObject *parent) + : QObject(parent) + , DObject(*new DQmlEnginePrivate(this)) +{ + D_D(DQmlEngine); + d->m_applet = applet; +} + +DQmlEngine::~DQmlEngine() +{ +} + +QObject *DQmlEngine::beginCreate() +{ + D_D(DQmlEngine); + QScopedPointer component(new QQmlComponent(engine(), this)); + const QString url = d->appletUrl(); + if (url.isEmpty()) + return nullptr; + + component->loadUrl(url); + if (component->isError()) { + qCWarning(dsLog()) << "Loading url failed" << component->errorString(); + return nullptr; + } + auto context = new QQmlContext(engine()); + auto object = component->beginCreate(context); + d->m_context = context; + d->m_rootObject = object; + d->m_component = component.take(); + return object; +} + +void DQmlEngine::completeCreate() +{ + D_D(DQmlEngine); + if (!d->m_component) + return; + + if (!d->m_component->isReady()) + return; + + d->m_component->completeCreate(); +} + +QObject *DQmlEngine::rootObject() const +{ + D_DC(DQmlEngine); + return d->m_rootObject; +} + +QQmlEngine *DQmlEngine::engine() +{ + D_D(DQmlEngine); + return d->engine(); +} + +DS_END_NAMESPACE diff --git a/frame/qmlengine.h b/frame/qmlengine.h new file mode 100644 index 000000000..a6e5d767f --- /dev/null +++ b/frame/qmlengine.h @@ -0,0 +1,35 @@ +// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include "dsglobal.h" + +#include +#include + +DS_BEGIN_NAMESPACE + +class DApplet; +class DQmlEnginePrivate; +/** + * @brief UI插件实例项 + */ +class Q_DECL_EXPORT DQmlEngine : public QObject, public DTK_CORE_NAMESPACE::DObject +{ + Q_OBJECT + D_DECLARE_PRIVATE(DQmlEngine) +public: + explicit DQmlEngine(QObject *parent = nullptr); + explicit DQmlEngine(DApplet *applet, QObject *parent = nullptr); + virtual ~DQmlEngine(); + + QObject *beginCreate(); + void completeCreate(); + QObject *rootObject() const; + + QQmlEngine *engine(); +}; + +DS_END_NAMESPACE diff --git a/misc/DDEShellConfig.cmake.in b/misc/DDEShellConfig.cmake.in new file mode 100644 index 000000000..2fb2431d5 --- /dev/null +++ b/misc/DDEShellConfig.cmake.in @@ -0,0 +1,16 @@ +@PACKAGE_INIT@ +include(CMakeFindDependencyMacro) +find_dependency(Dtk@DTK_VERSION_MAJOR@Core) +find_dependency(Dtk@DTK_VERSION_MAJOR@Gui) +find_package(Qt@QT_VERSION_MAJOR@ COMPONENTS Qml Quick REQUIRED) + +include(${CMAKE_CURRENT_LIST_DIR}/DDEShellTargets.cmake) +set(DDE_SHELL_PACKAGE_INSTALL_DIR @CMAKE_INSTALL_PREFIX@/@DDE_SHELL_PACKAGE_INSTALL_DIR@) +set(DDE_SHELL_PLUGIN_INSTALL_DIR @CMAKE_INSTALL_PREFIX@/@DDE_SHELL_PLUGIN_INSTALL_DIR@) +get_target_property(DDEShell_INCLUDE_DIRS DDEShell INTERFACE_INCLUDE_DIRECTORIES) +get_target_property(DDEShell_LIBRARY_DIRS DDEShell INTERFACE_LINK_DIRECTORIES) +set(DDEShell_INCLUDE_DIR ${DDEShell_INCLUDE_DIRS}) +set(DDEShell_LIBRARIES DDEShell) +check_required_components(Dtk@DTK_VERSION_MAJOR@Core) + +include("${CMAKE_CURRENT_LIST_DIR}/DDEShellPackageMacros.cmake") diff --git a/shell/CMakeLists.txt b/shell/CMakeLists.txt new file mode 100644 index 000000000..cf6d9402b --- /dev/null +++ b/shell/CMakeLists.txt @@ -0,0 +1,16 @@ +# SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +# +# SPDX-License-Identifier: CC0-1.0 + +add_executable(dde-shell + main.cpp +) + +target_link_libraries(dde-shell PRIVATE + dde-shell-frame + Qt${QT_VERSION_MAJOR}::Gui + Dtk${DTK_VERSION_MAJOR}::Gui +) + +install(TARGETS dde-shell DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) + diff --git a/shell/main.cpp b/shell/main.cpp new file mode 100644 index 000000000..4be1fb7de --- /dev/null +++ b/shell/main.cpp @@ -0,0 +1,62 @@ +// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later + +#include +#include + +#include +#include + +#include "applet.h" +#include "pluginloader.h" + +DS_USE_NAMESPACE +DGUI_USE_NAMESPACE + +int main(int argc, char *argv[]) +{ + QGuiApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); + QGuiApplication a(argc, argv); + a.setOrganizationName("deepin"); + a.setApplicationName("org.deepin.dde-shell"); + + QCommandLineParser parser; + parser.addHelpOption(); + parser.addVersionOption(); + + QCommandLineOption coronaOption("c", "collections of corona.", "corona", QString()); + parser.addOption(coronaOption); + QCommandLineOption testOption(QStringList() << "t" << "test", "application test."); + parser.addOption(testOption); + + parser.process(a); + + Dtk::Core::DLogManager::registerConsoleAppender(); + Dtk::Core::DLogManager::registerFileAppender(); + qInfo() << "Log path is:" << Dtk::Core::DLogManager::getlogFilePath(); + + QList pluginIds; + QList applets; + if (parser.isSet(testOption)) { + pluginIds << "org.deepin.ds.corona-example"; + } + if (parser.isSet(coronaOption)) { + pluginIds << parser.values(coronaOption); + } + qInfo() << "Loading plugin id" << pluginIds; + for (auto pluginId : pluginIds) { + auto applet = DPluginLoader::instance()->loadApplet(pluginId); + if (!applet) { + qWarning() << "Loading plugin failed:" << pluginId; + continue; + } + applets << applet; + } + for (auto applet : applets) { + applet->load(); + applet->init(); + } + + return a.exec(); +}