OpenSesame
Rapunzel Code Editor
DataMatrix
Support forum
Python Tutorials
MindProbe
Supported by

创建扩展

什么是 OpenSesame 扩展?

扩展向 OpenSesame 用户界面添加任意功能。例如,扩展可以在主工具栏或菜单栏中添加一个新条目。(要添加可用于实验的功能,请使用 插件。)

相关文件

一个或多个扩展被放置在扩展包中,它总是opensesame_extensions(这本身是一个所谓的隐含的命名空间包,但这是一个技术细节)的子包。假设你的扩展包叫做example,并且它包含一个叫做example_extension的单一扩展(可以有更多)。这将对应以下文件和文件夹结构:

opensesame_extensions/
    example/
        __init__.py               #可以为空,但必须存在
        example_extension/
            __init__.py           #包含扩展信息
            example_extension.py  #包含扩展类

扩展信息

扩展信息定义在扩展模块的__init__.py中,因此在我们的示例中,这是 opensesesame_extensions/example/example_extension/__init__.py

"""包含扩展描述的 docstring"""

# 标准图标名称
# - <https://specifications.freedesktop.org/icon-naming-spec/icon-naming-spec-latest.html>
icon = 'applications-accessories'
# 标签和工具提示用户创建默认操作时使用,即将其插入到菜单和/或工具栏(或两者皆非)
label = "示例扩展"
tooltip = "示例工具提示"
menu = {
    "index": -1,
    "separator_before": True,
    "separator_after": True,
    "submenu": "示例"
}
toolbar = {
    "index": -1,
    "separator_before": True,
    "separator_after": True
}
# 设置会在 cfg 对象中持续存储
settings = {
    "example_setting": "示例值"
}

扩展可以出现在 OpenSesame 的菜单或主工具栏中。这需要您像上面所示在__init__.py中定义几个字段:

  • label 是将出现在菜单中的文本。
  • icon 是一个遵循 freedesktop-compliant 图标名称 的规格,用于指定将出现在菜单和/或工具栏中的图标。
  • index 给出扩展在菜单/工具栏中的位置,并像 list 索引一样工作。也就是说,负数值相对于最后一个条目,-1 将扩展放在最后。

要让您的扩展响应菜单/工具栏的激活,请像下面的扩展代码中所示实现activate()方法。

编写扩展代码

主扩展代码放在 [extension_name].py中。这个文件通常只包含一个名为 [ExtensionName].py的类,即类名的驼峰形式等于插件名称,继承自 libqtopensesame.extensions.BaseExtension。 所以一个基本的(非功能性的)扩展类应该是这样的:

from libopensesame.py3compat import *
from libopensesame.oslogging import oslogger
from libqtopensesame.extensions import BaseExtension


class ExampleExtension(BaseExtension):
    """一个列出若干常见事件的示例扩展。类名应为
    folder_name 和 file_name 的 CamelCase 版本。所以在
    这种情况下,扩展文件夹(即 Python 包)和
    .py 文件(即 Python 模块)都叫做 example_extension,而
    类名则叫做 ExampleExtension
    """

    def activate(self):
        oslogger.debug('example_extension 扩展激活')

    def event_save_experiment(self, path):
        oslogger.debug(f'Event fired: save_experiment(path={path})')

    # 更多事件监听器,请参阅示例扩展源代码

监听事件

OpenSesame在发生重要事情时会触发事件。例如,当实验被保存时,“save_experiment”事件会被触发。要让您的扩展监听某个事件,只需实现一个名为event_[event name]的方法,如上所示。

请注意,某些事件需要关键字参数,例如save_experimentpath。您的函数的关键字签名必须符合预期的关键字签名。请参阅下面的事件概览以获取所有事件和预期关键字的完整列表。

构建软件包并上传至 pypi

构建扩展包并将其上传至pypi的方法与插件相同:

例子

具体示例可见:

其他示例可以在OpenSesame源代码的opensesame_extensions文件夹中找到:

事件概览

本概览列出了代码中触发的所有事件,因此,您的扩展可以通过实现相应的event_[eventname]()函数来监听它们。

change_experiment

触发于:general_properties.py

extension_manager.fire(u'change_experiment')

change_item

触发于:sequence.py

extension_manager.fire(u'change_item', name=self.name)

触发于:qtitem.py

extension_manager.fire(u'change_item', name=self.name)

触发于:loop.py

extension_manager.fire(u'change_item', name=self.name)

close

触发于:qtopensesame.py

extension_manager.fire(u'close')

delete_item

触发于:qtitem_store.py

extension_manager.fire(u'delete_item', name=name)

heartbeat

触发于:multiprocess_runner.py

extension_manager.fire(u'heartbeat')

ide_jump_to_line

触发于:SymbolSelector.py

extension_manager.fire('ide_jump_to_line', lineno=lineno)

触发于:OpenSesameIDE.py

extension_manager.fire('ide_jump_to_line', lineno=line_number)

ide_new_file

触发于:JupyterNotebook.py

extension_manager.fire(u'ide_new_file', source=code, ext=ext)

ide_save_current_file

触发于:OpenSesameIDE.py

extension_manager.fire('ide_save_current_file')

image_annotations_detect

触发于:JupyterNotebook.py

extension_manager.fire(u'image_annotations_detect', code=code)

jupyter_exception_occurred

触发于:transparent_jupyter_widget.py

extension_manager.fire('jupyter_exception_occurred')

jupyter_execute_finished

触发于:transparent_jupyter_widget.py

extension_manager.fire('jupyter_execute_finished')

jupyter_execute_result_text

触发于:transparent_jupyter_widget.py

extension_manager.fire('jupyter_execute_result_text', text=text)

jupyter_execute_start

触发于:transparent_jupyter_widget.py

extension_manager.fire('jupyter_execute_start')

jupyter_interrupt

触发于:OpenSesameIDE.py

extension_manager.fire(u'jupyter_interrupt')

jupyter_restart

console_bridge.py 中触发:

extension_manager.fire(u'jupyter_restart')

OpenSesameIDE.py 中触发:

extension_manager.fire(u'jupyter_restart')

jupyter_run_code

menubar.py 中触发:

extension_manager.fire('jupyter_run_code',
                                                     code=command)

jupyter_run_system_command

JupyterNotebook.py 中触发:

extension_manager.fire('jupyter_run_system_command', cmd=cmd)

jupyter_show_prompt

console_bridge.py 中触发:

extension_manager.fire(u'jupyter_show_prompt')

jupyter_write

console_bridge.py 中触发:

extension_manager.fire(u'jupyter_write', msg=s)

new_item

tree_overview.py 中触发:

extension_manager.fire(u'new_item', name=item.name,
                _type=item.item_type)

new_linked_copy

tree_overview.py 中触发:

extension_manager.fire('new_linked_copy', name=item_name)

notify

sequence.py 中触发:

extension_manager.fire(u'notify',
                    message=_(u'Sequence contains non-existing item: %s')

qtitem.py 中触发:

extension_manager.fire(u'notify',
                        message=_(u'"%s" is set to a variable or '
                        u'unknown value and can only be edited through '
                        u'the script.')

qtitem.py 中触发:

extension_manager.fire(u'notify',
                        message=_(u'"%s" is defined using '
                        'variables and can only be edited through the '
                        'script.')

qtitem.py 中触发:

extension_manager.fire(u'notify',
                        message=_(u'"%s" is defined using '
                        u'variables or has an invalid value, and can only be '
                        u'edited through the script.')

logger.py 中触发:

extension_manager.fire(u'notify',
                    message=_(u'You have multiple unlinked loggers. This can lead to messy log files.')

sketchpad_widget.py 中触发:

extension_manager.fire(u'notify', message=notification,
                category=u'info')

open_experiment

qtopensesame.py 中触发:

extension_manager.fire(u'open_experiment', path=path)

open_item

qtitem.py 中触发:

extension_manager.fire(u'open_item', name=self.name)

pause_experiment

base_runner.py 中触发:

extension_manager.fire(u'pause_experiment')

prepare_change_experiment

在:general_properties.py

extension_manager.fire(u'prepare_change_experiment')

prepare_delete_item

在:qtitem_store.py

extension_manager.fire(u'prepare_delete_item', name=name)

prepare_open_item

在:qtitem.py

extension_manager.fire(u'prepare_open_item', name=self.name)

prepare_purge_unused_items

在:unused_widget.py

extension_manager.fire(u'prepare_purge_unused_items')

prepare_regenerate

在:qtopensesame.py

extension_manager.fire(u'prepare_regenerate')

prepare_rename_item

在:qtitem_store.py

extension_manager.fire(u'prepare_rename_item', from_name=from_name,
            to_name=to_name)

purge_unused_items

在:unused_widget.py

extension_manager.fire(u'purge_unused_items')

pyqode_clear_breakpoints

在:OpenSesameIDE.py

extension_manager.fire('pyqode_clear_breakpoints')

pyqode_resume_auto_backend_restart

在:OpenSesameIDE.py

extension_manager.fire('pyqode_resume_auto_backend_restart')

在:OpenSesameIDE.py

extension_manager.fire('pyqode_resume_auto_backend_restart')

在:OpenSesameIDE.py

extension_manager.fire('pyqode_resume_auto_backend_restart')

在:OpenSesameIDE.py

extension_manager.fire('pyqode_resume_auto_backend_restart')

pyqode_select_indentation_mode

在:menubar.py

extension_manager.fire('pyqode_select_indentation_mode')

pyqode_suspend_auto_backend_restart

在:OpenSesameIDE.py

extension_manager.fire('pyqode_suspend_auto_backend_restart')

在:OpenSesameIDE.py

extension_manager.fire('pyqode_suspend_auto_backend_restart')

在:OpenSesameIDE.py

extension_manager.fire('pyqode_suspend_auto_backend_restart')

在:OpenSesameIDE.py

extension_manager.fire('pyqode_suspend_auto_backend_restart')

regenerate

在:qtopensesame.py

extension_manager.fire(u'regenerate')

在:qtopensesame.py

extension_manager.fire(u'regenerate')

register_editor

在:qtplugin.py

extension_manager.fire(u'register_editor', editor=editor)

rename_item

在:qtitem_store.py

extension_manager.fire(u'rename_item', from_name=from_name,
            to_name=to_name)

resume_experiment

在:base_runner.py

extension_manager.fire(u'resume_experiment')

run_experiment_canceled

在:base_runner.py

extension_manager.fire('run_experiment_canceled')

save_experiment

在:qtopensesame.py

extension_manager.fire(u'save_experiment', path=self.current_path)

startup

在:qtopensesame.py

extension_manager.fire(u'startup')

unregister_editor

在:OpenSesameIDE.py

extension_manager.fire('unregister_editor', editor=editor)
Supported by