qt creator源码全方面分析(2-10-4)
Plugin Life Cycle
为了能够编写Qt Creator插件,您必须了解启动或关闭Qt Creator时,插件管理器所采取的步骤。 本节详细描述插件所经历的过程和状态。
启动Qt Creator前,设置环境变量QT_LOGGING_RULES为qtc.extensionsystem*=true
,可以使能插件相关的调试日志输出,启动后,你就可以获取有关情况的更多信息。
启动Qt Creator时,插件管理器将执行以下操作:
-
在其搜索路径中查找所有动态库,并读取库元数据。所有没有元数据和IID不是
org.qt-project.Qt.QtCreatorPlugin
的库都将被忽略。这是加载插件可能失败的第一处地方,在最坏的元数据格式错误的情况下。 -
为每个插件创建ExtensionSystem::PluginSpec类的实例。此类是一个容器,包含来自插件规范的所有信息,并且还跟踪插件的状态。您可以通过插件管理器的plugins()函数,或者在插件被加载后,通过插件的pluginSpec()函数,来获取ExtensionSystem::PluginSpec实例。
-
将插件设置为
Read
状态。 -
验证插件的每个依赖项是否存在并且兼容。有关插件依赖性的更多信息,请参见Plugin Meta Data。
-
将插件设置为
Resolved
状态。 -
将所有插件排序到列表,我们称为加载队列,队列中,插件的依赖插件位于插件之后(但不一定直接紧靠在插件之后)。这将确保我们以正确的顺序加载和初始化插件。(我:官方文档有问题,应该是依赖的插件位于插件之前才对。)
-
加载插件库,并按照加载队列的顺序创建对应的IPlugin实例。此时,将调用插件的构造函数。被其他插件所依赖的插件先创建。
-
将插件设置为
Loaded
状态。 -
按照加载队列的顺序调用各个插件的initialize()函数。在初始化函数中,插件应确保所有的导出接口均已设置,并可供其他插件使用。插件可以假定他们所依赖的插件的导出接口均已设置好了。例如,
Core
插件设置了Core::ActionManager,Core::EditorManager
和所有其他公有可用接口,因此其他插件可以请求和使用它们。插件的initialize()函数对于下面来说是一个好地方:
- 在插件管理器的对象池中注册对象(请参阅The Plugin Manager, the Object Pool, and Registered Objects)
- 载入配置
- 添加新的菜单和菜单动作
- 连接到其他插件的信号
-
将插件设置为
Initialized
状态。 -
以加载队列的相反顺序调用所有插件的extensionsInitialized()函数。在extensionsInitialized函数之后,插件应该彻底完成初始化,设置和运行。插件可以假定依赖于它的插件也已彻底完成设置,并且可以完成初始化部分,供其他插件扩展。例如,
Core
插件可以假定所有插件均已注册其动作,并完成动作管理器的初始化。 -
将插件设置为
Running
状态。
在启动结束时,Core
插件的Core::ICore发送两个信号。在Qt Creator UI显示之前,它先发送coreAboutToOpen(),然后发送coreOpened()。
启动结束后,Qt Creator的事件循环运行时,插件管理器将按照加载队列的相反顺序调用所有插件的delayedInitialize()函数。调用在主线程上完成,但相隔几毫秒的延迟,以确保Qt Creator的响应能力。 在delayInitialize函数中,插件可以执行非关键性的初始化,如果在启动过程中进行,可能会不必要地延迟Qt Creator UI的显示。
在完成所有延迟的初始化之后,PluginManager将发送initializeDone()信号。
关闭之前,Core
插件Core::ICore发送coreAboutToClose()信号。 之后,插件管理器开始按顺序关闭:
- 按照加载队列的顺序,调用所有插件的aboutToShutdown()函数。 插件应在此处执行一些措施以加快实际关闭的速度,例如断开本来不需要调用的信号。 如果插件需要延迟实际关闭一段时间,例如,如果需要等待外部进程完成干净的退出,则插件可以从此函数中返回 ExtensionSystem::IPlugin::AsynchronousShutdown。 这将使插件管理器等待下一步,并保持主事件循环运行,直到所有请求AsynchronousShutdown的插件都发送了asynchronousShutdownFinished()信号为止。
- 按加载队列的相反顺序,删除插件的ExtensionSystem::IPlugin实例,来销毁所有插件。 此时,将调用插件析构函数。在释放内存和其他资源后,插件清理干净自己。
原创造福大家,共享改变世界
献出一片爱心,温暖作者心灵