diff --git a/TestPlugin/TestPlugin.json b/TestPlugin/TestPlugin.json new file mode 100644 index 0000000..1e81138 --- /dev/null +++ b/TestPlugin/TestPlugin.json @@ -0,0 +1,3 @@ +{ + "Keys" : [ ] +} diff --git a/TestPlugin/TestPlugin.pro b/TestPlugin/TestPlugin.pro new file mode 100644 index 0000000..9b19988 --- /dev/null +++ b/TestPlugin/TestPlugin.pro @@ -0,0 +1,36 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2022-09-27T14:57:42 +# +#------------------------------------------------- + +QT += core gui + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +TARGET = TestPlugin +TEMPLATE = lib +CONFIG += plugin + +# The following define makes your compiler emit warnings if you use +# any feature of Qt which has been marked as deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if you use deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +SOURCES += \ + testplugin.cpp + +HEADERS += \ + ../plugin/iwingtoolplg.h \ + testplugin.h +DISTFILES += TestPlugin.json + +RESOURCES += \ + resources.qrc + diff --git a/TestPlugin/logo.svg b/TestPlugin/logo.svg new file mode 100644 index 0000000..4db8539 --- /dev/null +++ b/TestPlugin/logo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/TestPlugin/resources.qrc b/TestPlugin/resources.qrc new file mode 100644 index 0000000..95ac425 --- /dev/null +++ b/TestPlugin/resources.qrc @@ -0,0 +1,5 @@ + + + logo.svg + + diff --git a/TestPlugin/testplugin.cpp b/TestPlugin/testplugin.cpp new file mode 100644 index 0000000..c03aadf --- /dev/null +++ b/TestPlugin/testplugin.cpp @@ -0,0 +1,78 @@ +#include "testplugin.h" + +TestPlugin::TestPlugin(QObject *parent) { Q_UNUSED(parent) } + +int TestPlugin::sdkVersion() { return SDKVERSION; } + +QString TestPlugin::signature() { return WINGSUMMER; } + +TestPlugin::~TestPlugin() {} + +bool TestPlugin::init(QList loadedplugin) { + Q_UNUSED(loadedplugin); + dialog = new QDialog; + dialog->setFixedSize(400, 400); + dialog->setWindowTitle("TestPluginConsole"); + dialog->setWindowFlags(Qt::CustomizeWindowHint | + Qt::WindowMinimizeButtonHint | + Qt::WindowMaximizeButtonHint); + tbinfo = new QTextBrowser(dialog); + tbinfo->setFixedSize(dialog->size()); + tbinfo->setUndoRedoEnabled(false); + dialog->show(); + return true; +} + +void TestPlugin::unload() { + dialog->close(); + delete dialog; +} + +QString TestPlugin::pluginName() { return "TestPlugin"; } + +QByteArray TestPlugin::provider() { return "testpro"; } + +QString TestPlugin::pluginAuthor() { return WINGSUMMER; } + +IWingToolPlg::Catagorys TestPlugin::pluginCatagory() { + return IWingToolPlg::Catagorys::Explor; +} + +uint TestPlugin::pluginVersion() { return 1; } + +QString TestPlugin::pluginComment() { return "This is a test plugin !"; } + +QIcon TestPlugin::pluginIcon() { return QIcon(":/TestPlugin/logo.svg"); } + +QStringList TestPlugin::pluginServices() { return {"func1", "func2", "func3"}; } + +HookIndex TestPlugin::getHookSubscribe() { return HookIndex::None; } + +QVariant TestPlugin::pluginServicePipe(int serviceID, QList params) { + switch (serviceID) { + case HostService: + if (params.first() == LoadedPluginMsg) { + testhotkey = registerHotkey( + QKeySequence(Qt::KeyboardModifier::ControlModifier | + Qt::KeyboardModifier::AltModifier | Qt::Key_Q)); + } + break; + case RemoteCallRes: + break; + case HotKeyTriggered: + tbinfo->append(QString("HotKeyTriggered : %1") + .arg(params.first().value().toString())); + break; + case 0: + break; + case 1: + break; + case 2: + break; + } + return QVariant(); +} + +#if QT_VERSION < 0x050000 +Q_EXPORT_PLUGIN2(TestPlugin, IWingToolPlg) +#endif // QT_VERSION < 0x050000 diff --git a/TestPlugin/testplugin.h b/TestPlugin/testplugin.h new file mode 100644 index 0000000..09a20df --- /dev/null +++ b/TestPlugin/testplugin.h @@ -0,0 +1,43 @@ +#ifndef GENERICPLUGIN_H +#define GENERICPLUGIN_H + +#include "../plugin/iwingtoolplg.h" +#include +#include + +class TestPlugin : public IWingToolPlg { + Q_OBJECT +#if QT_VERSION >= 0x050000 + Q_PLUGIN_METADATA(IID IWINGPLUGIN_INTERFACE_IID FILE "TestPlugin.json") +#endif // QT_VERSION >= 0x050000 + + Q_INTERFACES(IWingToolPlg) + +public: + TestPlugin(QObject *parent = nullptr); + int sdkVersion() override; + QString signature() override; + ~TestPlugin() override; + + bool init(QList loadedplugin) override; + void unload() override; + QString pluginName() override; + QByteArray provider() override; + QString pluginAuthor() override; + Catagorys pluginCatagory() override; + uint pluginVersion() override; + QString pluginComment() override; + QIcon pluginIcon() override; + QStringList pluginServices() override; + HookIndex getHookSubscribe() override; + +public slots: + QVariant pluginServicePipe(int serviceID, QList params) override; + +private: + QUuid testhotkey; + QDialog *dialog; + QTextBrowser *tbinfo; +}; + +#endif // GENERICPLUGIN_H diff --git a/control/pluginselector.cpp b/control/pluginselector.cpp index dfa5a5e..ef973bc 100644 --- a/control/pluginselector.cpp +++ b/control/pluginselector.cpp @@ -19,12 +19,13 @@ void PluginSelector::selectPlugin() { if (index >= 0) { auto plg = plgsys->plugin(index); setIcon(Utilities::processPluginIcon(plg)); - selplgindex = index; setText(plg->pluginName()); } else { setText("/"); setIcon(ICONRES("plugin")); } + selplgindex = index; + emit finished(); } int PluginSelector::getSelectedIndex() { return selplgindex; } diff --git a/control/pluginselector.h b/control/pluginselector.h index 0361cd6..408f896 100644 --- a/control/pluginselector.h +++ b/control/pluginselector.h @@ -8,6 +8,7 @@ DWIDGET_USE_NAMESPACE class PluginSelector : public DPushButton { + Q_OBJECT public: explicit PluginSelector(QWidget *parent = nullptr); @@ -18,6 +19,9 @@ public: int getSelectedIndex(); IWingToolPlg *getSelectedPlg(); +signals: + void finished(); + private: PluginSystem *plgsys; diff --git a/dialog/centerwindow.cpp b/dialog/centerwindow.cpp index 4a6e495..387ae10 100644 --- a/dialog/centerwindow.cpp +++ b/dialog/centerwindow.cpp @@ -213,7 +213,7 @@ CenterWindow::CenterWindow(DMainWindow *parent) tbplginfo->append(QObject::tr("Catagory:") + QObject::tr(e.valueToKey(int(plg->pluginCatagory())))); - tbplginfo->append(QObject::tr("Version") + + tbplginfo->append(QObject::tr("Version:") + QString::number(plg->pluginVersion())); tbplginfo->append(QObject::tr("Author:") + plg->pluginAuthor()); tbplginfo->append(QObject::tr("Comment:") + plg->pluginComment()); @@ -268,8 +268,10 @@ CenterWindow::CenterWindow(DMainWindow *parent) //初始化热键事件处理函数 QObject::connect(manager, &AppManager::hotkeyTirggered, this, [=](const QHotkey *hotkey) { - auto &task = scinfos[const_cast(hotkey)]; - this->runTask(task.process, task.params); + if (hotkeys.contains(const_cast(hotkey))) { + auto &task = scinfos[const_cast(hotkey)]; + this->runTask(task.process, task.params); + } }); QObject::connect(manager, &AppManager::hotkeyReleased, this, [=](const QHotkey *) { @@ -278,8 +280,10 @@ CenterWindow::CenterWindow(DMainWindow *parent) QObject::connect( manager, &AppManager::hotkeyEnableChanged, this, [=](bool value, const QHotkey *hotkey) { - tbhotkeys->item(hotkeys.indexOf(const_cast(hotkey)), 0) - ->setCheckState(value ? Qt::Checked : Qt::Unchecked); + if (hotkeys.contains(const_cast(hotkey))) { + tbhotkeys->item(hotkeys.indexOf(const_cast(hotkey)), 0) + ->setCheckState(value ? Qt::Checked : Qt::Unchecked); + } }); } diff --git a/dialog/pluginseldialog.cpp b/dialog/pluginseldialog.cpp index 85b6ae2..0cd18a9 100644 --- a/dialog/pluginseldialog.cpp +++ b/dialog/pluginseldialog.cpp @@ -2,6 +2,7 @@ #include "plugin/pluginsystem.h" #include "utilities.h" #include +#include #include #include @@ -52,8 +53,15 @@ PluginSelDialog::PluginSelDialog(DDialog *parent) : DDialog(parent) { auto group = new DButtonBox(this); QList blist; auto b = new DButtonBoxButton(tr("Select"), this); - connect(b, &DButtonBoxButton::clicked, this, - [=] { this->done(lsplgs->currentRow()); }); + connect(b, &DButtonBoxButton::clicked, this, [=] { + auto sel = lsplgs->currentRow(); + if (sel < 0) { + DMessageManager::instance()->sendMessage(this, ProgramIcon, + tr("NoSelection")); + return; + } + this->done(sel); + }); blist.append(b); b = new DButtonBoxButton(tr("NoPlugin"), this); connect(b, &DButtonBoxButton::clicked, this, [=] { this->done(-1); }); diff --git a/dialog/pluginseldialog.h b/dialog/pluginseldialog.h index 4bcfd99..7e70177 100644 --- a/dialog/pluginseldialog.h +++ b/dialog/pluginseldialog.h @@ -9,6 +9,7 @@ DWIDGET_USE_NAMESPACE class PluginSelDialog : public DDialog { + Q_OBJECT public: PluginSelDialog(DDialog *parent = nullptr); diff --git a/dialog/shortcuteditdialog.cpp b/dialog/shortcuteditdialog.cpp index 970d3a2..47976ad 100644 --- a/dialog/shortcuteditdialog.cpp +++ b/dialog/shortcuteditdialog.cpp @@ -29,15 +29,35 @@ ShortCutEditDialog::ShortCutEditDialog(bool enabled, QKeySequence seq, addContent(new DLabel(tr("Plugin"), this)); addSpacing(5); ps = new PluginSelector(this); + connect(ps, &PluginSelector::finished, this, [=] { + auto plg = ps->getSelectedPlg(); + if (plg) { + lblp->setText(tr("Service")); + fcedit->setVisible(false); + cbService->clear(); + cbService->addItems(plg->pluginServices()); + cbService->setVisible(true); + } else { + lblp->setText(tr("FilePath")); + fcedit->setVisible(true); + cbService->setVisible(false); + } + }); addContent(ps); addSpacing(10); - addContent(new DLabel(tr("FilePath"), this)); + lblp = new DLabel(tr("FilePath"), this); + addContent(lblp); addSpacing(5); fcedit = new DFileChooserEdit(this); fcedit->initDialog(); fcedit->setText(process); addContent(fcedit); + + cbService = new DComboBox(this); + cbService->setVisible(false); + addContent(cbService); + addSpacing(10); addContent(new DLabel(tr("Param"), this)); diff --git a/dialog/shortcuteditdialog.h b/dialog/shortcuteditdialog.h index da79c27..2463ec4 100644 --- a/dialog/shortcuteditdialog.h +++ b/dialog/shortcuteditdialog.h @@ -6,15 +6,18 @@ #include "class/appmanager.h" #include "control/pluginselector.h" #include +#include #include #include #include +#include #include #include DWIDGET_USE_NAMESPACE class ShortCutEditDialog : public DDialog { + Q_OBJECT public: ShortCutEditDialog(bool enabled = true, QKeySequence seq = QKeySequence(), QString process = QString(), QString params = QString(), @@ -37,6 +40,9 @@ private: DFileChooserEdit *fcedit; DLineEdit *dledit; DKeySequenceEdit *ksedit; + + DLabel *lblp; + DComboBox *cbService; }; #endif // SHORTCUTEDITDIALOG_H diff --git a/plugin/iwingtoolplg.h b/plugin/iwingtoolplg.h index b59c95a..519e96c 100644 --- a/plugin/iwingtoolplg.h +++ b/plugin/iwingtoolplg.h @@ -1,6 +1,8 @@ #ifndef IWINGTOOLPLG_H #define IWINGTOOLPLG_H +#include +#include #include #include #include @@ -14,8 +16,19 @@ #define LoadingPluginMsg QVariant::fromValue('l') #define LoadedPluginMsg QVariant::fromValue('L') -#define HostService -1 -#define RemoteCallRes -2 + +/*=================================*/ + +// 插件系统预定义服务号,全部为负数 +// 如果服务号为非负数,则表示为插件服务 + +#define HostService -1 // 插件加载消息服务 +#define RemoteCallRes -2 // 远程调用结果服务 +#define HotKeyTriggered -3 // 热键触发服务 +#define HotKeyReleased -4 //热键释放服务 +#define HotkeyEnableChanged -5 // 热键状态更改服务 + +/*=================================*/ struct WingPluginInfo { QString pluginName; @@ -100,13 +113,13 @@ public: signals: // 注册热键,如果被占用则返回 -1 表示失败(通常是重复), // 大于等于 0 则表示成功,返回句柄 - QUuid registerHotkey(QKeySequence &keyseq); + QUuid registerHotkey(QKeySequence keyseq); // 修改热键状态,其中 id 为注册热键句柄,enable 为热键的新状态 bool enableHotKey(const QUuid id, bool enabled = true); // 修改热键 - bool editHotkey(const QUuid id, QKeySequence &seq); + bool editHotkey(const QUuid id, QKeySequence seq); // 注销热键,其中 id 为注册热键句柄 bool unregisterHotkey(const QUuid id); diff --git a/plugin/pluginsystem.cpp b/plugin/pluginsystem.cpp index ff6f4ce..cfad2a0 100644 --- a/plugin/pluginsystem.cpp +++ b/plugin/pluginsystem.cpp @@ -70,7 +70,33 @@ PluginSystem::PluginSystem(QObject *parent) }); connect(manager, &AppManager::hotkeyTirggered, this, [=](const QHotkey *hotkey) { - + auto uuid = uhmap.key(const_cast(hotkey), QUuid()); + if (uuid.isNull()) + return; + int id; + auto plg = this->loopUpHotkey(uuid, id); + if (plg) + plg->pluginServicePipe(HotKeyTriggered, {uuid}); + }); + connect(manager, &AppManager::hotkeyReleased, this, + [=](const QHotkey *hotkey) { + auto uuid = uhmap.key(const_cast(hotkey), QUuid()); + if (uuid.isNull()) + return; + int id; + auto plg = this->loopUpHotkey(uuid, id); + if (plg) + plg->pluginServicePipe(HotKeyReleased, {uuid}); + }); + connect(manager, &AppManager::hotkeyEnableChanged, this, + [=](bool value, const QHotkey *hotkey) { + auto uuid = uhmap.key(const_cast(hotkey), QUuid()); + if (uuid.isNull()) + return; + int id; + auto plg = this->loopUpHotkey(uuid, id); + if (plg) + plg->pluginServicePipe(HotkeyEnableChanged, {value, uuid}); }); LoadPlugin(); @@ -85,8 +111,12 @@ PluginSystem::~PluginSystem() { bool PluginSystem::LoadPlugin() { QDir plugindir(QCoreApplication::applicationDirPath() + "/plugin"); +#ifdef QT_DEBUG + plugindir.setNameFilters(QStringList("*.so")); +#else plugindir.setNameFilters(QStringList("*.wingplg")); - auto plgs = plugindir.entryInfoList(); +#endif + auto plgs = plugindir.entryInfoList(QDir::Files); for (auto item : plgs) { loadPlugin(item); } @@ -194,7 +224,7 @@ void PluginSystem::loadPlugin(QFileInfo fileinfo) { // 连接信号 connect(p, &IWingToolPlg::registerHotkey, this, - [=](QKeySequence &keyseq) { + [=](QKeySequence keyseq) { auto sender = qobject_cast(QObject::sender()); if (sender == nullptr) return QUuid(); @@ -234,7 +264,7 @@ void PluginSystem::loadPlugin(QFileInfo fileinfo) { return false; }); connect(p, &IWingToolPlg::editHotkey, this, - [=](const QUuid id, QKeySequence &seq) { + [=](const QUuid id, QKeySequence seq) { auto sender = qobject_cast(QObject::sender()); if (sender == nullptr) return false; @@ -305,3 +335,14 @@ QList PluginSystem::pluginRegisteredHotkey(IWingToolPlg *plg) { } return keys; } + +IWingToolPlg *PluginSystem::loopUpHotkey(QUuid uuid, int &index) { + for (auto plg : m_plgs) { + auto res = m_plghk[plg].indexOf(uuid); + if (res >= 0) { + index = res; + return plg; + } + } + return nullptr; +} diff --git a/plugin/pluginsystem.h b/plugin/pluginsystem.h index 5ae87a0..e66da4d 100644 --- a/plugin/pluginsystem.h +++ b/plugin/pluginsystem.h @@ -42,6 +42,9 @@ public: QList pluginRegisteredHotkey(IWingToolPlg *plg); +private: + IWingToolPlg *loopUpHotkey(QUuid uuid, int &index); + private: static PluginSystem *m_instance; AppManager *manager; diff --git a/utilities.h b/utilities.h index 9afa291..1efd61b 100644 --- a/utilities.h +++ b/utilities.h @@ -19,10 +19,10 @@ struct ShortCutEditRes { class Utilities { public: static QIcon processPluginIcon(IWingToolPlg *plg) { - if (plg->pluginIcon().availableSizes().count()) { - return plg->pluginIcon(); + if (plg->pluginIcon().isNull()) { + return ICONRES("plugin"); } - return ICONRES("plugin"); + return plg->pluginIcon(); } };