Skip to content
Nathan Osman edited this page Nov 4, 2017 · 2 revisions

Plugins were introduced in NitroShare 0.4 and provide an easy way to customize the functionality of the application.

Overview

This page will guide you through the process of writing a simple plugin. The purpose of the plugin is to add an action to the system tray menu that when clicked displays the name of the current device.

Initial Setup

Begin by creating a file named CMakeLists.txt with the following content:

cmake_minimum_required(VERSION 3.2.0)
project(myplugin)

# Automatically run Qt's MOC compiler on headers
set(CMAKE_AUTOMOC ON)

# Plugin will use Qt widgets and must link against libnitroshare
find_package(Qt5Widgets 5.4 REQUIRED)
find_package(nitroshare 0.4 REQUIRED)

set(SRC
    myplugin.h
    myplugin.cpp
    shownameaction.h
    shownameaction.cpp
)

# Create the module from the source files specified above
add_library(myplugin MODULE ${SRC})

# Enable C++11
set_target_properties(myplugin PROPERTIES
    CXX_STANDARD 11
)

# Link against Qt and libnitroshare
target_link_libraries(myplugin Qt5::Widgets nitroshare)

Each plugin must include some basic metadata that provides its name, a brief description of what it does, its dependencies, etc. Our plugin is relatively simple and has only one dependency: "ui". This is a special dependency that indicates the plugin can only be loaded when NitroShare is run in a graphical environment.

The metadata is provided by a file named myplugin.json:

{
    "Name": "myplugin",
    "Title": "My Plugin",
    "Vendor": "Your Name Here",
    "Version": "0.1",
    "Description": "Display the current device name",
    "Dependencies": [
        "ui"
    ]
}

Plugin Code

The next step is to create the header file myplugin.h:

#ifndef MYPLUGIN_H
#define MYPLUGIN_H

#include <nitroshare/iplugin.h>

class ShowNameAction;

class MyPlugin : public IPlugin
{
    Q_OBJECT
    Q_PLUGIN_METADATA(IID Plugin_iid FILE "myplugin.json")

public:

    virtual void initialize(Application *application);
    virtual void cleanup(Application *application);

private:

    ShowNameAction *mAction;
};

#endif // MYPLUGIN_H

Every plugin must include a class that derives from IPlugin. This class must implement the two virtual methods shown above whose purposes are as follows:

  • initialize() is invoked when the plugin is loaded
  • cleanup() is invoked when the plugin is unloaded

Both of these methods are passed a single parameter - a pointer to an Application instance. This class provides access to most of NitroShare's functionality. The mAction member will be explained later.

The corresponding source file, myplugin.cpp, contains the following content:

#include <nitroshare/actionregistry.h>
#include <nitroshare/application.h>

#include "myplugin.h"
#include "shownameaction.h"

void MyPlugin::initialize(Application *application)
{
    mAction = new ShowNameAction(application);
    application->actionRegistry()->add(mAction);
}

void MyPlugin::cleanup(Application *application)
{
    application->actionRegistry()->remove(mAction);
    delete mAction;
}

When the plugin is loaded, it initializes mAction and registers the action with the action registry. Likewise, when the plugin is unloaded, it removes the action from the registry.

Action Code

The files above reference a class named ShowNameAction. This header, shownameaction.h, is shown below:

#ifndef SHOWNAMEACTION_H
#define SHOWNAMEACTION_H

#include <nitroshare/action.h>

class Application;

class ShowNameAction : public Action
{
    Q_OBJECT
    Q_PROPERTY(bool ui READ ui)
    Q_PROPERTY(QString title READ title)

public:

    explicit ShowNameAction(Application *application);

    virtual QString name() const;

    bool ui() const;
    QString title() const;

public slots:

    virtual QVariant invoke(const QVariantMap &params = QVariantMap());

private:

    Application *mApplication;
};

#endif // SHOWNAMEACTION_H

There is a lot happening in this file:

  • Every action must derive from the Action class
  • The name() method returns the internal name used for the action
  • The ui property (and method) indicate that this is a graphical action and should be shown in the menu
  • The title property (and method) determine the text shown in the menu
  • The invoke() slot is called when the action is run (when the user clicks the menu item)

The implementation file, shownameaction.cpp is shown below:

#include <QMessageBox>

#include <nitroshare/application.h>

#include "shownameaction.h"

ShowNameAction::ShowNameAction(Application *application)
    : mApplication(application)
{
}

QString ShowNameAction::name() const
{
    return tr("showname");
}

bool ShowNameAction::ui() const
{
    return true;
}

QString ShowNameAction::title() const
{
    return tr("Show device name...");
}

QVariant ShowNameAction::invoke(const QVariantMap &params)
{
    QMessageBox::information(
        nullptr,
        tr("Information"),
        tr("Device name: %1").arg(mApplication->deviceName())
    );
    return true;
}
Clone this wiki locally