Plugins tutorial

Andrei Kopats edited this page Jan 13, 2016 · 18 revisions

This page gives very brief introduction to plugin interface. See plugin API documentation for full information.

Hello world plugin

Let's create our first plugin. This manual gives step-by-step instructions. Final code may be found at enki/example-plugin/helloworld.py. If you want to test it quickly, just copy this file to enki/plugins/ and restart Enki.

The beginning

For creating "Hello, world" plugin, go to Enki sources directory, and create file enki/plugins/helloworld.py with the next code:

from PyQt4.QtGui import QMessageBox

# core is main enki.core singletone. It is usually used for getting pointers to other singletones
from enki.core.core import core

class Plugin:
    """During initialization, core imports all modules and packages in enki/plugins directory,
    searches for Plugin class in every module and creates an instance
    """
    def __init__(self):
        QMessageBox.information(core.mainWindow(), "Hello, world", "Plugin loaded")

    def terminate(self):
        """This method is called by core for each plugin during termination
        """
        QMessageBox.information(core.mainWindow(), "Hello, world", "Plugin terminated")

Now restart Enki and see, that your plugin is loaded

Add new action to the main menu

class Plugin:
    def __init__(self):
        self._addAction()

    def _addAction(self):
        """Add action to main menu
        This action uses embedded icons. You can find list of icons in icons/ directory at project root
        """
        action = core.actionManager().addAction( "mHelp/aSayHello",
                                                 "Say Hello...",
                                                 QIcon(':enkiicons/enki.png'))
        core.actionManager().setDefaultShortcut(action, "Ctrl+Alt+Shift+H")
        action.triggered.connect(self._sayHello)

    def _sayHello(self):
        """Handler for main menu action
        """
        QMessageBox.information(core.mainWindow(), "Hello, world", "Menu action has been triggered!")

Don't forget to add import QIcon at the top of file.

Now run Enki and check, if you have action in Help menu. You even might go to Settings->Application shortcuts and set new shortcut for it.

Add dock widget to the main window

import enki.widgets.dockwidget

class MyDock(enki.widgets.dockwidget.DockWidget):
    def __init__(self):
        enki.widgets.dockwidget.DockWidget.__init__(self,
                                                    core.mainWindow(),
                                                    "Hello dock",
                                                    QIcon(":enkiicons/help.png"),
                                                    "Alt+H")

        self.label = QLabel("This is Hello World dock")
        self.setWidget(self.label)

class Plugin:
    def __init__(self):
        self._createDock()

    def _createDock(self):
        """Create dock widget and add it to main window
        """
        self._dock = MyDock()
        core.mainWindow().addDockWidget(Qt.RightDockWidgetArea, self._dock)

Read and write settings from the config

class Plugin:
    def __init__(self):
        self._readSettings()

    def _readSettings(self):
        """Read settings from core configuration file
        """
        if not "HelloWorld" in core.config():  # first start
            core.config()["HelloWorld"] = {}
            core.config()["HelloWorld"]["VeryImportantSetting"] = "the correct value"
        self._dock.label.setText('Option value: %s' % core.config()["HelloWorld"]["VeryImportantSetting"])

    def _writeSettings(self):
        """This method is never called.
        Just an example implementation
        """
        core.config()["HelloWorld"]["VeryImportantSetting"] = "new value"
        # Don't forget to flush config!
        # if settings has been edited with main settings dialogue, it will be flushed automatically
        core.config().flush()

Here we dynamically add our option to the main configuration file during first start. You also can edit enki/config/enki.default.json

Get notified when something interesting happens

class Plugin:
    def __init__(self):
        core.workspace().currentDocumentChanged.connect(self._onDocumentChanged)

    def _onDocumentChanged(self, old, new):
        """Current document has been changed. Let's notify the user
        """
        if new is not None:
            core.mainWindow().appendMessage("Current file is '%s'" % new.fileName(), 1000)

Check the API docs for other useful signals

Add my options to the settings dialogue

from enki.core.uisettings import TextOption

class SettingsPage(QWidget):
    """Settings page for Hello World plugin
    """
    def __init__(self, parent):
        QWidget.__init__(self, parent)
        self._layout = QHBoxLayout(self)
        self._label = QLabel("Very important option", self)
        self._layout.addWidget(self._label)
        self.edit = QLineEdit(self)
        self._layout.addWidget(self.edit)

class Plugin:
    def __init__(self):
        core.uiSettingsManager().dialogAccepted.connect(self._applySettings)
        core.uiSettingsManager().aboutToExecute.connect(self._onSettingsDialogAboutToExecute)

    def _applySettings(self):
        """Dialog has been accepted. Apply settings
        """
        self._dock.label.setText('Option value: %s' % core.config()["HelloWorld"]["VeryImportantOption"])

    def _onSettingsDialogAboutToExecute(self, dialog):
        """UI settings dialogue is about to execute.
        Add own options
        """
        page = SettingsPage(dialog)
        dialog.appendPage(u"Hello World", page, QIcon(':/enkiicons/help.png'))

        # Options
        dialog.appendOption(TextOption(dialog, core.config(), "HelloWorld/VeryImportantOption", page.edit))

Now go to Edit->Settings->Hello World, edit the text and check, if it is updated on UI. Than restart Enki and check, if new value has been loaded from settings.

Congratulations! We just have created absolutelly useless plugin. And you are ready to create something more valuable. Full plugin API documentation and Enki team will help you.

Read also about coding style and rules at the Hacking guide.