Step by step example for ContextFreePlugin

The following sections describe the steps that are required to create a plugin which derives from ContextFreePlugin. For simplicity, a separate project is created and the generated binary will to be copied to the plugin directory of the given cube installation.

Qt project file

To create a cube plugins, a makefile and source files have to be generated. The makefile can be generated automatically from a Qt project file

First we specify the path to the "cube-config" script of the cube installation. This script delivers correct flags for compiling and linking.

CUBE_CONFIG = /opt/cube/bin/cube-config
INCLUDEPATH += $$system($$CUBE_CONFIG --gui-include-path) $$system($$CUBE_CONFIG --cube-include-path)
LIBS += $$system($$CUBE_CONFIG --gui-ldflags) $$system($$CUBE_CONFIG --cube-ldflags)
DESTDIR = $$system($$CUBE_CONFIG --cube-dir)/plugins
TEMPLATE = lib
CONFIG += plugin
HEADERS = ContextFreePlugin.h
SOURCES = ContextFreePlugin.cpp
TARGET = $$qtLibraryTarget(ContextFreeExamplePlugin)

qmake && make will build the first plugin example libContextFreeExamplePlugin.so. The plugin will be copied to the plugin directory, e.g. /opt/cube/lib64/plugins.

ContextFreePluginExample.h

The example describes a minimal context free plugin. The plugin becames active, if Cube is started without an input file, or if the cube file is closed.

The complete source of the example can be found in $CUBE_INSTALL_PREFIX/share/doc/cube/example/gui/context-free.

A context free plugin has to derive from ContextFreePlugin. To use Qt's signal and slot mechanism it also has to derive from QObject.

class ContextFreePluginExample : public QObject, public ContextFreePlugin

The class header is followed by the following macro definitions:

  • Q_OBJECT is required to handle signals and slots.

  • Q_INTERFACES( ContextFreePlugin ) tells Qt that the class implements the ContextFreePlugin interface and generates the method qt_metacast(char*) to cast the plugin object to ContextFreePlugin using the class name given as as character array.

  • For Qt versions >= 5.0 the plugin has to be exported using the Q_PLUGIN_METADATA() macro. The unique plugin name "ContextFreePlugin" is assigned. For Qt versions < 5.0, Q_EXPORT_PLUGIN2 has be be used (see Section 'ContextFreeExample.cpp' ).
class ContextFreePluginExample : public QObject, public ContextFreePlugin
{
Q_OBJECT
Q_INTERFACES( ContextFreePlugin )
#if QT_VERSION >= 0x050000
Q_PLUGIN_METADATA( IID "ContextFreePluginExample" )
#endif

The class ContextFreePluginExample has to implement all pure virtual methods from ContextFreePlugin.

public:
// ContextFreePlugin interface
virtual QString name() const;
virtual void opened( ContextFreeServices* service );
virtual void closed();
virtual void version( int& major,int& minor,int& bugfix ) const;
virtual QString getHelpText() const;
private slots:
void startAction();
private:
ContextFreeServices* service;
};

ContextFreeExample.cpp

For Qt versions < 5.0, Q_EXPORT_PLUGIN2 is used to export the plugin. The first argument is a unique name for the plugin, the second the name of the plugin class.

#if QT_VERSION < 0x050000
Q_EXPORT_PLUGIN2( ContextFreePluginExample, ContextFreePluginExample )
#endif
#include "ContextFreePluginExample.h"
#include "ContextFreeServices.h"
#include "Cube.h"

The function opened(ContextFreeServices* service) is the starting point of our plugin. With service->getWidget() we get a widget on Cube's main screen, in which we can place the GUI elements of our plugin. In this example, only one button will be placed on the main screen. Activation of this button will call the slot function startAction().

void
ContextFreePluginExample::opened( ContextFreeServices* service )
{
this->service = service;
qDebug() << "context free plugin opened";
QWidget *widget = service->getWidget();
QVBoxLayout* layout = new QVBoxLayout();
widget->setLayout( layout );
QPushButton *but = new QPushButton("Load cube file");
layout->addWidget( but );
connect(but, SIGNAL(clicked()), this, SLOT(startAction()) );
}

The function closed() is called if the plugin gets inactive because a cube file is loaded or the Cube GUI is closed. All resources which have been allocated in opened() have to be deleted here.

void
ContextFreePluginExample::closed()
{
qDebug() << "context free plugin closed";
}

This function is called, if the user clicks on the Button "Load cube file". Usually, a context free plugin will create cube data. In this small example, it simply loads the cube file which is choosen from a file dialog.

void
ContextFreePluginExample::startAction()
{
QString openFileName = QFileDialog::getOpenFileName( service->getWidget(),
tr( "Choose a file to open" ),
"",
tr( "Cube3/4 files (*cube *cube.gz *.cubex);;Cube4 files (*.cubex);;Cube3 files (*.cube.gz *.cube);;All files (*.*);;All files (*)" ) );
cube::Cube *cube = new cube::Cube();
cube->openCubeReport( openFileName.toStdString() );
service->openCube(cube); // will be deleted automatically, if user closes cube
}

Each plugin has to set a version number. If several plugins with the same identifier (see function name()) exist, the one with the highest version number will be loaded.

void ContextFreeExample::version( int& major, int& minor, int& bugfix ) const
{
major = 1; minor = 0; bugfix = 0;
}

This function returns the unique plugin name. Only one plugin with this name will be loaded.

QString ContextFreePluginExample::name() const
{
return "ContextFreePluginExample";
}

The following function returns a text to describe the plugin. It will be used by help menu of the cube GUI.

QString
ContextFreePluginExample::getHelpText() const
{
return "context free plugin help text";
}

Scalasca     Copyright © 1998–2015 Forschungszentrum Jülich, Jülich Supercomputing Centre