File indexing completed on 2024-12-15 04:01:20
0001 /* 0002 * SPDX-FileCopyrightText: 2019-2023 Mattia Basaglia <dev@dragon.best> 0003 * 0004 * SPDX-License-Identifier: GPL-3.0-or-later 0005 */ 0006 0007 #pragma once 0008 0009 #include <memory> 0010 0011 #include <QDir> 0012 0013 #include "app/log/log.hpp" 0014 #include "plugin/service.hpp" 0015 0016 namespace app::scripting { 0017 0018 class ScriptEngine; 0019 0020 } // namespace app::scripting 0021 0022 namespace glaxnimate::plugin { 0023 0024 struct PluginData 0025 { 0026 QDir dir; 0027 QString id; 0028 0029 int version = 0; 0030 const app::scripting::ScriptEngine* engine = nullptr; 0031 QString engine_name; 0032 QString name; 0033 QString author; 0034 QString icon; 0035 QString description; 0036 std::vector<std::unique_ptr<PluginService>> services; 0037 }; 0038 0039 class Plugin 0040 { 0041 public: 0042 Plugin(PluginData data, bool user_installed) 0043 : data_(std::move(data)), user_installed_(user_installed) 0044 { 0045 icon_ = QIcon::fromTheme("libreoffice-extension"); 0046 icon_ = make_icon(data_.icon); 0047 for ( const auto& ps : data_.services ) 0048 ps->set_plugin(this); 0049 } 0050 0051 const PluginData& data() const { return data_; } 0052 0053 QString file(const QString& path) const 0054 { 0055 if ( !QDir::isRelativePath(path) ) 0056 return {}; 0057 0058 if ( !data_.dir.exists(path) ) 0059 return {}; 0060 0061 return data_.dir.cleanPath(path); 0062 } 0063 0064 QIcon make_icon(const QString& icon) const 0065 { 0066 if ( !icon.isEmpty() ) 0067 { 0068 if ( icon.startsWith("theme:") ) 0069 return QIcon::fromTheme(icon.mid(6)); 0070 if ( data_.dir.exists(icon) ) 0071 return QIcon(data_.dir.absoluteFilePath(icon)); 0072 } 0073 return icon_; 0074 } 0075 0076 bool available() const 0077 { 0078 return data_.engine; 0079 } 0080 0081 bool can_enable() const 0082 { 0083 return !enabled_ && data_.engine; 0084 } 0085 0086 bool can_disable() const 0087 { 0088 return enabled_; 0089 } 0090 0091 void enable() 0092 { 0093 if ( !can_enable() ) 0094 return; 0095 0096 for ( const auto& svc : data_.services ) 0097 svc->enable(); 0098 0099 enabled_ = true; 0100 } 0101 0102 void disable() 0103 { 0104 if ( !can_disable() ) 0105 return; 0106 0107 for ( const auto& svc : data_.services ) 0108 svc->disable(); 0109 0110 enabled_ = false; 0111 } 0112 0113 bool user_installed() const 0114 { 0115 return user_installed_; 0116 } 0117 0118 const QIcon& icon() const 0119 { 0120 return icon_; 0121 } 0122 0123 bool run_script(const PluginScript& script, const QVariantList& args) const; 0124 0125 bool enabled() const { return enabled_; } 0126 0127 app::log::Log logger() const 0128 { 0129 return {"Plugins", data_.name}; 0130 } 0131 0132 private: 0133 PluginData data_; 0134 bool enabled_ = false; 0135 bool user_installed_ = false; 0136 QIcon icon_; 0137 }; 0138 0139 class Executor; 0140 0141 0142 class PluginRegistry : public QObject 0143 { 0144 Q_OBJECT 0145 0146 public: 0147 static PluginRegistry& instance() 0148 { 0149 static PluginRegistry instance; 0150 return instance; 0151 } 0152 0153 void load(); 0154 0155 const std::vector<std::unique_ptr<Plugin>>& plugins() const { return plugins_; } 0156 0157 bool load_plugin(const QString& path, bool user_installed); 0158 0159 Plugin* plugin(const QString& id) const; 0160 0161 Executor* executor() const; 0162 void set_executor(Executor* exec); 0163 QVariant global_parameter(const QString& name) const; 0164 0165 Q_SIGNALS: 0166 void loaded(); 0167 0168 private: 0169 PluginRegistry() = default; 0170 PluginRegistry(const PluginRegistry&) = delete; 0171 ~PluginRegistry() = default; 0172 0173 void load_service(const QJsonObject& jobj, PluginData& data) const; 0174 PluginScript load_script(const QJsonObject& jobj) const; 0175 void load_setting(const QJsonObject& jobj, PluginScript& script) const; 0176 QVariantMap load_choices(const QJsonValue& val) const; 0177 0178 std::vector<std::unique_ptr<Plugin>> plugins_; 0179 Executor* executor_ = nullptr; 0180 QMap<QString, int> names; 0181 app::log::Log logger{"Plugins"}; 0182 }; 0183 0184 } // namespace glaxnimate::plugin