Tutorial: Creating a QCAD Plugin

This tutorial explains how to compile a QCAD plugin.

Table of Contents

 

Introduction

QCAD plugins can be used to extend QCAD with functionality implemented in C or C++. 

Implementing RPluginInterface

All QCAD plugins must be directly or indirectly derived from QObject and the abstract base class RPluginInterface.

File RExamplePlugin.h

For our first, minimalistic example plugin, we add empty or minimalistic implementations for most methods of RPluginInterface directly to the header file. This initial structure of the header file can be copied to get a first working plugin that can be loaded into QCAD.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
#include <QObject>
#include <QScriptEngine>

#include "RPluginInterface.h"

class RExamplePlugin : public QObject, public RPluginInterface
{
    Q_OBJECT
    Q_INTERFACES(RPluginInterface)
#if QT_VERSION >= 0x050000
    Q_PLUGIN_METADATA(IID "org.qcad.exampleplugin")
#endif

public:
    virtual bool init() { return true; }
    virtual void uninit(bool) {}
    virtual void postInit(InitStatus status) {}
    virtual void initScriptExtensions(QScriptEngine& engine) {}
    virtual RPluginInfo getPluginInfo();
    virtual bool checkLicense() { return true; }
};

 

File RExamplePlugin.cpp

For method getPluginInfo, we add a simple implementation to the cpp file for the benefit of seeing something in the about dialog of QCAD.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
#include "RExamplePlugin.h"

RPluginInfo RExamplePlugin::getPluginInfo() {
    RPluginInfo ret;
    ret.set("Version", "1.0");
    ret.set("ID", "EXAMPLE");
    ret.set("Name", "Example Plugin");
    ret.set("License", "GPLv3");
    ret.set("URL", "http://qcad.org");
    return ret;
}

#if QT_VERSION < 0x050000
QT_BEGIN_NAMESPACE
Q_EXPORT_PLUGIN2(example, RExamplePlugin)
QT_END_NAMESPACE
#endif

 

File exampleplugin.pro

To compile our plugin, we also need a Qt project file that can be turned into a Makefile with Qt qmake.

1
2
3
4
5
6
7
8
9
CONFIG      += plugin
TARGET      = example
include(../../../shared.pri)

TEMPLATE    = lib
HEADERS     = RExamplePlugin.h
SOURCES     = RExamplePlugin.cpp
DESTDIR     = ../../../plugins
LIBS += -lqcadcore -lqcadgui -lqcadecmaapi

The include on line 3 should point to the file shared.pri of the QCAD source code installation (e.g. qcad/shared.pri). As DESTDIR, you may want to choose the plugins folder of a working QCAD installation, so the plugin is compiled in the right place from where it can also be loaded by QCAD.

Compilation

Your plugin can be compiled with these three files, creating the file qcad/plugins/qcadexample.dll or libqcadexample.so or libqcadexample.dylib.

Note: if you run a QCAD binary compiled in debug mode, the plugin must also be compiled in debug mode. If you run QCAD in release mode, the plugin must be compiled in release mode as well.

To compile the plugin in debug mode run:

Linux / macOS:

qmake
make debug

Windows:

qmake
nmake debug

To compile in release mode, run make release or nmake release instead.

Obviously, the plugin won't do anything useful yet, but you should be able to see your plugin in the QCAD about dialog:

If you cannot see your plugin, please check for errors on in the terminal while starting QCAD. You might also see an error message in the about dialog.

Compiling Scripts as Resources into a Plugin

QCAD plugins may be used to compile a collection of scripts and other resources (ui files, icons, etc.) into a plugin. This has the advantage that the code of multiple ECMAScript files can be bundled inside a single, compiled binary file. Plugins tend to load faster than individual files from disk and take up less disk space.

File scripts/MyTool/MyTool.js

Let's assume there's a folder scripts/MyTool with a file MyTool.js which contains a QCAD tool, implemented in ECMAScript. The tool adds itself at the top of the Misc menu and outputs "Hello World" when triggered. 

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
include("scripts/EAction.js");

function MyTool(guiAction) {
    EAction.call(this, guiAction);
}

MyTool.prototype = new EAction();

MyTool.prototype.beginEvent = function() {
    EAction.prototype.beginEvent.call(this);

    EAction.handleUserMessage("Hello World");

    this.terminate();
};

MyTool.init = function(basePath) {
    var action = new RGuiAction("&MyTool", RMainWindowQt.getMainWindow());
    action.setRequiresDocument(true);
    action.setScriptFile(basePath + "/MyTool.js");
    action.setGroupSortOrder(0);
    action.setSortOrder(0);
    action.setWidgetNames(["MiscMenu"]);
};

 

File scripts.qrc

To compile this script tool into our C++ plugin, we need to create a Qt resource file which points qmake to the file we want to compile into the plugin:

1
2
3
4
5
<!DOCTYPE RCC><RCC version="1.0">
  <qresource>
    <file alias="scripts/MyTool/MyTool.js">scripts/MyTool/MyTool.js</file>
  </qresource>
</RCC>

The qrc file lists the paths under which resources are to be made available in Qt's resource system (alias="scripts/MyTool/MyTool.js") and the actual path where the file can be found on disk (used for compilation only). The above example means that there is a file on disk under scripts/MyTool/MyTool.js which will be compiled into the plugin. As soon as the plugin is loaded, the file will be available under path ":/scripts/MyTool/MyTool.js". QCAD will find the tool automatically under that path since it scans folder "scripts" as well as ":/scripts" for scripts.

We also need to add the qrc file to the project file (exampleplugin.pro) by adding the following line:

RESOURCES = scripts.qrc

After editing the file exampleplugin.pro, run qmake and make again and load the plugin. There should now be a menu entry "MyTool" at the top of the Misc menu in QCAD.

Source Code

You can find the complete source code for this example plugin at:

https://github.com/qcad/qcad/tree/master/support/examples/exampleplugin

Troubleshooting

  • If your plugin compiles but cannot be loaded by QCAD, please make sure that the same Qt version is used as for QCAD  (see Help > About QCAD). Please make sure that if QCAD is run in release mode, your plugin is also compiled in release mode.
  • Launch QCAD from a terminal or the command line and check the console output for error messages. Output messages in your plugin to confirm it is being loaded. For example in your init function.
  • Check the about dialog (Help > About QCAD > Plugins) for error messages.