• Qt Creator插件


    本文归属于  Qt实验室-CSDN博客 系列文章

    这里以Qt Creator 4.15.2版本的源码为示例进行分析

    源码结构如下,为了追溯其插件加载过程,从main.cpp入手

    Qt Creator的插件目录,生成的插件,好几十个呢

     Qt Creator插件的读取

    int main(int argc, char **argv)中以下代码创建插件的管理

    1. PluginManager pluginManager;
    2. PluginManager::setPluginIID(QLatin1String("org.qt-project.Qt.QtCreatorPlugin"));
    3. PluginManager::setGlobalSettings(globalSettings);
    4. PluginManager::setSettings(settings);

     int main(int argc, char **argv)中以下设置插件的读取目录,读取所有插件信息

    1. const QStringList pluginPaths = getPluginPaths() + options.customPluginPaths;
    2. PluginManager::setPluginPaths(pluginPaths);//读取插件目录下的插件

    从 PluginManager::setPluginPaths(pluginPaths)调用追溯到如下

    1. void PluginManagerPrivate::setPluginPaths(const QStringList &paths)
    2. {
    3. qCDebug(pluginLog) << "Plugin search paths:" << paths;
    4. qCDebug(pluginLog) << "Required IID:" << pluginIID;
    5. pluginPaths = paths;
    6. readSettings();
    7. readPluginPaths();
    8. }

    继续追溯void PluginManagerPrivate::readPluginPaths()

    1. for (const QString &pluginFile : pluginFiles(pluginPaths)) {
    2. PluginSpec *spec = PluginSpec::read(pluginFile);
    1. PluginSpec *PluginSpec::read(const QString &filePath)
    2. {
    3. auto spec = new PluginSpec;
    4. if (!spec->d->read(filePath)) { // not a Qt Creator plugin
    5. delete spec;
    6. return nullptr;
    7. }
    8. return spec;
    9. }

    其中bool PluginSpecPrivate::read(const QString &fileName)方法读取了插件的基本信息

    Qt Creator 加载插件

    从main函数中的 PluginManager::loadPlugins();开始追溯插件的加载

    1. void PluginManagerPrivate::loadPlugins()
    2. {
    3. //所有插件都会从loaded-->initialized-->running
    4. const QVector<PluginSpec *> queue = loadQueue();
    5. Utils::setMimeStartupPhase(MimeStartupPhase::PluginsLoading);
    6. for (PluginSpec *spec : queue)
    7. loadPlugin(spec, PluginSpec::Loaded);
    8. Utils::setMimeStartupPhase(MimeStartupPhase::PluginsInitializing);
    9. for (PluginSpec *spec : queue)
    10. loadPlugin(spec, PluginSpec::Initialized);
    11. Utils::setMimeStartupPhase(MimeStartupPhase::PluginsDelayedInitializing);
    12. Utils::reverseForeach(queue, [this](PluginSpec *spec) {
    13. loadPlugin(spec, PluginSpec::Running);//从这里开始加载插件...step2
    14. if (spec->state() == PluginSpec::Running) {
    15. delayedInitializeQueue.push(spec);
    16. } else {
    17. // Plugin initialization failed, so cleanup after it
    18. spec->d->kill();
    19. }
    20. });
    21. ...
    22. }

    插件加载的几个主要步骤,load, initialize, run

    在 void PluginManagerPrivate::loadPlugin(PluginSpec *spec, PluginSpec::State destState)中

    1. switch (destState) {
    2. case PluginSpec::Loaded:
    3. profilingReport(">loadLibrary", spec);
    4. spec->d->loadLibrary();
    5. profilingReport(", spec);
    6. break;
    7. case PluginSpec::Initialized:
    8. profilingReport(">initializePlugin", spec);
    9. spec->d->initializePlugin();
    10. profilingReport(", spec);
    11. break;
    12. case PluginSpec::Stopped:
    13. profilingReport(">stop", spec);
    14. if (spec->d->stop() == IPlugin::AsynchronousShutdown) {
    15. asynchronousPlugins << spec;
    16. connect(spec->plugin(), &IPlugin::asynchronousShutdownFinished,
    17. this, &PluginManagerPrivate::asyncShutdownFinished);
    18. }
    19. profilingReport(", spec);
    20. break;
    21. default:
    22. break;
    23. }

    继续追溯bool PluginSpecPrivate::loadLibrary()

    1. if (!loader.load()) {//这里是加载插件
    2. hasError = true;
    3. errorString = QDir::toNativeSeparators(filePath)
    4. + QString::fromLatin1(": ") + loader.errorString();
    5. return false;
    6. }

    Qt Creator插件

    合格的插件需要继承自IPlugin抽象类

    以CppEditorPlugin为例

    class CppEditorPlugin : public ExtensionSystem::IPlugin

    看一下IPlugin类

    1. #pragma once
    2. #include "extensionsystem_global.h"
    3. #include
    4. namespace ExtensionSystem {
    5. namespace Internal {
    6. class IPluginPrivate;
    7. class PluginSpecPrivate;
    8. }
    9. class PluginManager;
    10. class PluginSpec;
    11. class EXTENSIONSYSTEM_EXPORT IPlugin : public QObject
    12. {
    13. Q_OBJECT
    14. public:
    15. enum ShutdownFlag {
    16. SynchronousShutdown,
    17. AsynchronousShutdown
    18. };
    19. IPlugin();
    20. ~IPlugin() override;
    21. virtual bool initialize(const QStringList &arguments, QString *errorString) = 0;
    22. virtual void extensionsInitialized() {}
    23. virtual bool delayedInitialize() { return false; }
    24. virtual ShutdownFlag aboutToShutdown() { return SynchronousShutdown; }
    25. virtual QObject *remoteCommand(const QStringList & /* options */,
    26. const QString & /* workingDirectory */,
    27. const QStringList & /* arguments */) { return nullptr; }
    28. virtual QVector createTestObjects() const;
    29. PluginSpec *pluginSpec() const;
    30. signals:
    31. void asynchronousShutdownFinished();
    32. private:
    33. Internal::IPluginPrivate *d;
    34. friend class Internal::PluginSpecPrivate;
    35. };
    36. } // namespace ExtensionSystem

     实现具体的插件类时,以下方法是必须重写的

    virtual bool initialize(const QStringList &arguments, QString *errorString) = 0;

  • 相关阅读:
    Web基础与HTTP协议
    解析五育融合之下的steam教育模式
    什么是Fetch API?与传统的AJAX相比,有什么优势?
    6 JS 和 Jquery 删除标签元素
    exness整理马斯克收购推特需要解决三个问题
    CopyOnWriteArrayList源码分析
    Maven安装配置及注意事项
    【Linux】线程安全-生产者消费者模型
    微信小程序前端生成动态海报图
    word文档莫名其妙的丢失了怎么办?7个方案恢复
  • 原文地址:https://blog.csdn.net/xiyangxiaoguo/article/details/134265385