Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions include/DtkCore/DPlugin
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#include "dplugin.h"
37 changes: 37 additions & 0 deletions include/util/dplugin.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// SPDX-FileCopyrightText: 2017 - 2023 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: LGPL-3.0-or-later

#ifndef DPLUGIN_H
#define DPLUGIN_H

#include "dtkcore_global.h"

#include <QLibrary>

#include <memory>

DCORE_BEGIN_NAMESPACE

class DPluginPrivate;

class DPlugin : public QObject

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should DPlugin derive from DObject? If yes, it's better to use D_DECLARE_PRIVATE. And remember to make DPluginPrivate derive from DObjectPrivate.

{
Q_OBJECT;

public:
static QList<std::shared_ptr<DPlugin>> listPlugins(const QStringList &extraLocations = {});

const QScopedPointer<QLibrary> library;
QString name();

private:
DPlugin(const QString &name, const QString &filename, const QString &version, QObject *parent = nullptr);

QScopedPointer<DPluginPrivate> d_ptr;
Q_DECLARE_PRIVATE(DPlugin);
};

DCORE_END_NAMESPACE

#endif
129 changes: 129 additions & 0 deletions src/util/dplugin.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
// SPDX-FileCopyrightText: 2019 - 2023 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: LGPL-3.0-or-later

#include "dplugin.h"
#include "dplugin_p.h"

#include <QStandardPaths>
#include <QDebug>
#include <QDir>
#include <QJsonDocument>
#include <QJsonObject>

DCORE_BEGIN_NAMESPACE

QList<std::shared_ptr<DPlugin>> DPlugin::listPlugins(const QStringList &extraDirs)
{
auto pluginDirs = QStandardPaths::standardLocations(QStandardPaths::AppDataLocation);

for (auto &pluginDir : pluginDirs) {
pluginDir = QStringList{pluginDir, "plugins"}.join(QDir::separator());
}

pluginDirs.append(extraDirs);

qDebug() << "Searching dplugins in" << pluginDirs;

QList<std::shared_ptr<DPlugin>> plugins{};

for (const auto &pluginDir : pluginDirs) {
plugins << DPluginPrivate::searchPluginsInPath(pluginDir);
}

return plugins;
}

QList<std::shared_ptr<DPlugin>> DPluginPrivate::searchPluginsInPath(const QString &pluginDirPath)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
QList<std::shared_ptr<DPlugin>> DPluginPrivate::searchPluginsInPath(const QString &pluginDirPath)
QList<std::shared_ptr<DPlugin>> DPluginPrivate::load(const QString &pluginDirPath)

{
auto const pluginDir = QDir(pluginDirPath);
auto const entryList = pluginDir.entryList();

@kegechen kegechen Jul 17, 2023

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

可以通过 QDir::Filter::Files 过滤一下,下面就不用判断是不是文件了


QList<std::shared_ptr<DPlugin>> result{};

for (auto const &entry : entryList) {
auto filePath = QStringList{pluginDirPath, entry}.join(QDir::separator());
auto fileInfo = QFileInfo(filePath);

// NOTE(black_desk): we do not load a large file (>4KB) into memory
if (!fileInfo.isFile() || fileInfo.size() > (1 << 11)) {
continue;
}

QFile file(filePath);
file.open(QIODevice::ReadOnly);
auto content = file.readAll();

auto plugin = DPluginPrivate::pluginFromJsonContent(content);
if (!plugin) {
qWarning() << "Ignore invalid plugin config:" << filePath;
continue;
}
result << plugin;
}

return result;
}

std::shared_ptr<DPlugin> DPluginPrivate::pluginFromJsonContent(const QByteArray &content)
{
QJsonParseError err;
auto jsonDoc = QJsonDocument::fromJson(content, &err);
if (err.error || !jsonDoc.isObject()) {
return nullptr;
}

auto config = jsonDoc.object();
if (!DPluginPrivate::configCompatible(config["pluginConfigVersion"])) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • json 的示例文件可以在注释或者什么地方提供一下。
  • 既然已知是 plugin 的配置文件,是不是 json 中的 key 可以去掉 plugin 的前缀

return nullptr;
}

auto nameVar = config["pluginName"];
if (!nameVar.isString()) {
return nullptr;
}

auto name = nameVar.toString();

auto versionVar = config["pluginVersion"];
if (!nameVar.isString()) {
return nullptr;
}

auto version = versionVar.toString();

auto filenameVar = config["pluginFilename"];
if (!filenameVar.isString()) {
return nullptr;
}

auto filename = filenameVar.toString();

return std::shared_ptr<DPlugin>(new DPlugin(name, filename, version));
}

DPlugin::DPlugin(const QString &name, const QString &filename, const QString &version, QObject *parent)
: QObject(parent)
, library(new QLibrary(filename, version))
, d_ptr(new DPluginPrivate(name, this))
{
}

QString DPlugin::name()
{
Q_D(DPlugin);
return d->name;
}

bool DPluginPrivate::configCompatible(const QJsonValueRef &version)
{
return version.isString() && version.toString() == "1";
}

DPluginPrivate::DPluginPrivate(const QString &name, DPlugin *parent)
: QObject(parent)
, name(name)
{
}

DCORE_END_NAMESPACE
34 changes: 34 additions & 0 deletions src/util/dplugin_p.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: LGPL-3.0-or-later

#ifndef DPLUGIN_P_H
#define DPLUGIN_P_H

#include "dplugin.h"

#include <QJsonValueRef>

DCORE_BEGIN_NAMESPACE

class DPlugin;

class DPluginPrivate : public QObject
{
Q_OBJECT;

public:
explicit DPluginPrivate(const QString &name, DPlugin *parent);
const QString name;

static QList<std::shared_ptr<DPlugin>> searchPluginsInPath(const QString &pluginDirPath);
static bool configCompatible(const QJsonValueRef &version);
static std::shared_ptr<DPlugin> pluginFromJsonContent(const QByteArray &content);

DPlugin *q_ptr;
Q_DECLARE_PUBLIC(DPlugin);
};

DCORE_END_NAMESPACE

#endif
58 changes: 21 additions & 37 deletions src/util/util.cmake
Original file line number Diff line number Diff line change
@@ -1,44 +1,28 @@
set(UTILS_SOURCE
${CMAKE_CURRENT_LIST_DIR}/dabstractunitformatter.cpp
${CMAKE_CURRENT_LIST_DIR}/ddbusextendedabstractinterface.cpp
${CMAKE_CURRENT_LIST_DIR}/ddbusextendedpendingcallwatcher.cpp
${CMAKE_CURRENT_LIST_DIR}/ddbusinterface.cpp
${CMAKE_CURRENT_LIST_DIR}/ddbussender.cpp
${CMAKE_CURRENT_LIST_DIR}/ddisksizeformatter.cpp
${CMAKE_CURRENT_LIST_DIR}/dexportedinterface.cpp
${CMAKE_CURRENT_LIST_DIR}/dnotifysender.cpp
${CMAKE_CURRENT_LIST_DIR}/dpinyin.cpp
${CMAKE_CURRENT_LIST_DIR}/dplugin.cpp
${CMAKE_CURRENT_LIST_DIR}/drecentmanager.cpp
${CMAKE_CURRENT_LIST_DIR}/dtextencoding.cpp
${CMAKE_CURRENT_LIST_DIR}/dthreadutils.cpp
${CMAKE_CURRENT_LIST_DIR}/dtimedloop.cpp
${CMAKE_CURRENT_LIST_DIR}/dtimeunitformatter.cpp
${CMAKE_CURRENT_LIST_DIR}/dvtablehook.cpp
)

if(LINUX)
set(UTILS_SOURCE
${CMAKE_CURRENT_LIST_DIR}/dtimeunitformatter.cpp
${CMAKE_CURRENT_LIST_DIR}/dabstractunitformatter.cpp
${CMAKE_CURRENT_LIST_DIR}/ddisksizeformatter.cpp
${CMAKE_CURRENT_LIST_DIR}/ddbussender.cpp
${CMAKE_CURRENT_LIST_DIR}/drecentmanager.cpp
${CMAKE_CURRENT_LIST_DIR}/dnotifysender.cpp
${CMAKE_CURRENT_LIST_DIR}/dpinyin.cpp
${CMAKE_CURRENT_LIST_DIR}/dexportedinterface.cpp
${CMAKE_CURRENT_LIST_DIR}/dvtablehook.cpp
${CMAKE_CURRENT_LIST_DIR}/dthreadutils.cpp
${CMAKE_CURRENT_LIST_DIR}/dtimedloop.cpp
set(UTILS_SOURCE ${UTILS_SOURCE}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I recommend using list(APPEND).

${CMAKE_CURRENT_LIST_DIR}/dfileservices_linux.cpp
${CMAKE_CURRENT_LIST_DIR}/dexportedinterface.cpp
${CMAKE_CURRENT_LIST_DIR}/ddbusinterface.cpp
${CMAKE_CURRENT_LIST_DIR}/ddbusextendedabstractinterface.cpp
${CMAKE_CURRENT_LIST_DIR}/ddbusextendedpendingcallwatcher.cpp
${CMAKE_CURRENT_LIST_DIR}/dtextencoding.cpp
)
else()
set(UTILS_SOURCE
${CMAKE_CURRENT_LIST_DIR}/dtimeunitformatter.cpp
${CMAKE_CURRENT_LIST_DIR}/dabstractunitformatter.cpp
${CMAKE_CURRENT_LIST_DIR}/ddisksizeformatter.cpp
${CMAKE_CURRENT_LIST_DIR}/ddbussender.cpp
${CMAKE_CURRENT_LIST_DIR}/drecentmanager.cpp
${CMAKE_CURRENT_LIST_DIR}/dnotifysender.cpp
${CMAKE_CURRENT_LIST_DIR}/dpinyin.cpp
${CMAKE_CURRENT_LIST_DIR}/dexportedinterface.cpp
${CMAKE_CURRENT_LIST_DIR}/dvtablehook.cpp
${CMAKE_CURRENT_LIST_DIR}/dthreadutils.cpp
${CMAKE_CURRENT_LIST_DIR}/dtimedloop.cpp
${CMAKE_CURRENT_LIST_DIR}/dfileservices_dummy.cpp
${CMAKE_CURRENT_LIST_DIR}/dexportedinterface.cpp
${CMAKE_CURRENT_LIST_DIR}/ddbusinterface.cpp
${CMAKE_CURRENT_LIST_DIR}/ddbusextendedabstractinterface.cpp
${CMAKE_CURRENT_LIST_DIR}/ddbusextendedpendingcallwatcher.cpp
${CMAKE_CURRENT_LIST_DIR}/dtextencoding.cpp
)
endif()

file(GLOB UTILS_HEADER
${CMAKE_CURRENT_LIST_DIR}/../../include/util/*
${CMAKE_CURRENT_LIST_DIR}/ddbusinterface_p.h
Expand Down