Extending Albert using C++

This page focuses on the practical aspects of extending Albert using C++ and its peculiarities. To get a high level overview of common concepts of the API refer to the general section.

A native plugin is a Qt Plugin, i.e. a shared library providing an instance of the class PluginInstance.

Albert provides C and CMake macros that implement conventions to streamline the plugin development process and to reduce the considerable amount of boilerplate code required to a few lines of code.

CMake

Having a standardized plugin project structure the albert_plugin macro takes care of most of the CMake boilerplate code. It is part of the albert CMake module and can be included using find_package(Albert REQUIRED). Read its documentation in the header of the CMake module before you proceed.

A minimal working CMakeLists.txt (See also the CMakeLists.txt files of the official plugins):

project(my_plugin VERSION 1.0)
find_package(Albert REQUIRED)
albert_plugin()

This is the standard plugin directory structure of a plugin:

─┬─  my_plugin      
 ├──  CMakeLists.txt      
 ├──  metadata.json
 ├─┬─  src    
 │ └──  …
 └─┬─  i18n        
   └──  …       

A basic metadata file looks like this (See also the metadata.json files of the official plugins):

{
    "name": "My Plugin",
    "description": "Do useful stuff",
    "authors": ["@myname"],
    "license": "MIT",
    "url": "https://github.com/myusername/my-albert-plugin",
}

C++

Albert plugins ultimately have to inherit the QObject and PluginInstance class and contain the ALBERT_PLUGIN macro in the declaration body.

A basic plugin looks like this (See also the plugin header files of the official plugins):

#pragma once
#include <albert/extensionplugin.h>
#include <albert/triggerqueryhandler.h>

class Plugin : public QObject, public albert::PluginInstance
{
    ALBERT_PLUGIN
};

Usually you dont want to subclass PluginInstance directly but rather ExtensionPlugin which implements the Extension interface using the metadata of the plugin instance.

#pragma once
#include <albert/extensionplugin.h>
#include <albert/triggerqueryhandler.h>

class Plugin : public albert::ExtensionPlugin,
               public albert::TriggerQueryHandler
{
    ALBERT_PLUGIN
    void handleTriggerQuery(albert::Query &) override {}
};

From here on it depends on the interface you want to implement. Read through the albert namespace reference. See the official native plugins as a reference. Concise examples to start with are: debug, timezones, hash or urlhandler.

Plugin directories

The plugin directories depends on the platform and the build type.

  • Linux:
    • ~/.local/{lib,lib64}/albert
    • /usr/local/{lib,lib64}/albert
    • /usr/lib/${MULTIARCH_TUPLE}/albert
    • /usr/{lib,lib64}/albert
  • macOS:
    • $BUNDLE_PATH/Contents/PlugIns
    • ~/Library/Application Support/Albert/plugins

The plugin directories are scanned in the order of the above list. On start Albert scans the plugin directories for available plugins. Since identifiers have to be unique, duplicate plugins with the same identifier (project name) are skipped.