Skip to content

PluginAPI

hagantsa edited this page Feb 29, 2024 · 3 revisions

Plugin API of Kactus2

Kactus2 has a basic C++ plugin interface for extending the functionality of Kactus2 via .dll/.so plugins. The plugins are implemented as standard Qt plugins (see http://doc.qt.io/qt-6.2/plugins-howto.html).

The current plugin architecture is illustrated in the image below. The API allows three types of plugins: generators, source analyzers, and import plugins. Each of them is an interface derived from IPlugin. Basically all plugins are derived from one of these three interfaces and must implement functions defined in the derived interface and IPlugin. More details about the interfaces is described within this document.

Kactus2 exports the library interface (KactusAPI/include/LibraryInterface.h) to be available for use in generator plugins. Through this interface plugins may read, modify and create IP-XACT components and designs. Other plugins may access and modify the affected IP-XACT component. Usage of the library interface is described further within this document.

Plugin architecture

class IPlugin

All plugin interfaces inherit from a common IPlugin interface which all plugins must implement. It is used by Kactus2 to acquire plugin information. Most of the plugins do not inherit this interface directly, but some derived interface.

Functions:

  • virtual QString getName(): Returns the name of the plugin.

  • virtual QString getVersion(): Returns the version of the plugin.

  • virtual QString getDescription(): Returns the plugin description (what it is, what it does, etc.).

  • virtual QString getVendor(): Returns the vendor of the plugin.

  • virtual QString getLicense(): Returns the license for the plugin (e.g. GPL2).

  • virtual QString getLicenseHolder(): Returns the license holder i.e. who is the plugin licensed to (e.g. Public or Tampere University of Technology).

  • virtual QWidget* getSettingsWidget(): This can be used to show custom plugin-specific settings UI in the Kactus2 settings dialog. A QWidget should be returned even if the plugin has no custom settings.

  • virtual PluginSettingsModel* getSettingsModel(): This is used to access the settings modified by function getSettingsWidget(). If a null pointer is returned, no settings are manipulated.

  • virtual QList<ExternalProgramRequirement> getProgramRequirements(): This can be used to indicate what external programs the plugin needs in order to operate correctly. This allows Kactus2 to show settings to set paths where those external programs are located.

class PluginSettingsModel is the base interface for plugin settings model.

  • virtual void loadSettings(QSettings& settings): Loads plugin settings from the given settings store. Is called when Kactus2 loads the plugin.
  • virtual void saveSettings(QSettings& settings): Saves plugin settings to the given settings store. Is called when Kactus2 applies changes to settings.
  • virtual bool validateSettings(): Validates the settings of the plugin.

struct ExternalProgramRequirement contains options for required external program paths for plugin with following variables:

  • QString name_: Identifies the program to run.
  • QString description_: Explains the required program for user.
  • QString filters_: Contains the filters for the QFileDialog to select correct type of files.

class ISourceAnalyzerPlugin

Kactus2 contains a dependency analyzer to manage and visualize dependencies between source files of a component. Source analyzer plugins are used in the dependency analyzer to add support for different code languages and even custom file types. Single source analyzer plugin implements support for a single file type or language.

Functions:

  • virtual QStringList getSupportedFileTypes(): Returns the list of file types this plugin can run analysis for. File type is described as an IP-XACT style string, e.g. cppSource or vhdlSource. Kactus2 includes a settings page for setting which file extensions map to which file types so that the analyzer plugin doesn't have to hard-code the supported extensions.

  • virtual QString calculateHash(): Calculates a language-dependent hash for the analyzed file. Hash calculation here may ignore white space and comments.

    • Parameters:
    • QString const& filename: The name of the file.
    • Returns: The hash value for the file.
  • virtual void beginAnalysis(): This function is called once when the dependency analysis scan is started. It gives the plugin the ability to do preparations before any file is analyzed.

    • Parameters:
    • Component const* component: The component to which the dependency scan is being run.
    • QString const& componentPath: The path to the directory where the component is located.
  • virtual void endAnalysis(): This function is called once after the dependency analysis scan has completed. It allows the plugin to make cleanup operations after the dependency scan has been finished, e.g. destroy internal data structures.

    • Parameters:
    • Component const* component: The component to which the dependency scan is being run.
    • QString const& componentPath: The path to the directory where the component is located.
  • virtual QList<FileDependencyDesc> getFileDependencies(): Retrieves all file dependencies the given file has.

    • Parameters:
    • Component const* component: The component to which the dependency scan is being run.
    • QString const& componentPath: The path to the directory where the component is located.
    • QString const& filename: The name of the file to which the analysis is run.
    • Returns: The list of found dependencies.

struct FileDependencyDesc contains file dependency descriptions with following variables:

  • QString filename: The name of the dependent file, for example "componentName.vhd".
  • QString description: Possible automatically deduced description for the dependency, for example "Component instantiation for entity componentName".

Example of an analyzer plugin class definition:

    #include <KactusAPI/include/ISourceAnalyzerPlugin.h>
    
    class CppSourceAnalyzer : public QObject, public ISourceAnalyzerPlugin
    {
        Q_OBJECT
        // Explained at http://doc.qt.io/qt-6.2/qtplugin.html#Q_PLUGIN_METADATA
        Q_PLUGIN_METADATA(IID "kactus2.plugins.CppSourceAnalyzer" FILE "CppSourceAnalyzer.json")
    
        Q_INTERFACES(IPlugin)
        Q_INTERFACES(ISourceAnalyzerPlugin)
    
    public:
        ...
    };

class ImportPlugin

Import plugins can be used to create elements e.g. ports in components from implementation source files e.g. VHDL files. The import can be run in component wizard. After selecting the top-level file, all active import plugins, whose accepted file types match the selected file, will be run.

Functions:

  • virtual QStringList getSupportedFileTypes(): Returns the file types supported by the plugin.

  • virtual QString getCompatibilityWarnings(): Returns a compatibility warning concerning the import plugin usage. Can be empty.

  • virtual QStringList getFileComponents(QString const& input): Gets component declarations from the selected input file.

    • Parameters:
    • QString const& input: The selected input file.
    • Returns: List of component declarations found in the selected input.
  • virtual QString getComponentName(QString const& componentDeclaration): Gets the name of the selected component declaration.

    • Parameters:
    • QString const& componentDeclaration: The selected component declaration.
    • Returns: The name of the selected component declaration.
  • virtual void import(): Runs the import by parsing the given input and applying the parsed elements to the given component.

    • Parameters:
    • QString const& input: The input text to parse.
    • QString const& componentDeclaration: Declaration of the selected component.
    • QSharedPointer<Component> targetComponent: The component to apply all imported changes to.

Example of a import plugin class definition:

    #include <KactusAPI/include/ImportPlugin.h>
    #include <KactusAPI/include/HighlightSource.h>
    
    class VERILOGIMPORT_EXPORT VerilogImporter: public QObject, public ImportPlugin, public HighlightSource
    {
        Q_OBJECT
        // Explained at http://doc.qt.io/qt-6.2/qtplugin.html#Q_PLUGIN_METADATA
        Q_PLUGIN_METADATA(IID "kactus2.plugins.verilogimportplugin" FILE "verilogimportplugin.json")
    
        Q_INTERFACES(IPlugin)
        Q_INTERFACES(ImportPlugin)
    
    public:
        ...
    };

If an import plugin also supports highlighting code in the source file visualizer, it needs to inherit interface HighlightSource and implement the following function:

  • virtual void setHighlighter(Highlighter* highlighter): Sets the given highlighter to be used by the source.

A highlighter provided for a plugin has following functions:

  • virtual void applyHighlight(): Called when the text should be highlighted with the given color.

    • Parameters:
    • QString const& text: The text to highlight.
    • QColor const& highlightColor: The color of the highlight.
  • virtual void applyHighlight(): Called when a section should be highlighted with the given color.

    • Parameters:
    • int beginPosition: The beginning character index.
    • int endPosition: The end character index.
    • QColor const& color: The color of the highlight.
  • virtual void applyFontColor(): Called when the font color of a text should be changed to the given color.

    • Parameters:
    • QString const& text: The text whose font to change.
    • QColor const& color: The color of the text.

Example usage:

    void SampleImporter::setHighlighter(Highlighter* highlighter)
    {
        // Save a pointer to the provided highlighter for later use.
        highlighter_ = highlighter;
    }
    
    void SampleImporter::import(QString const& input, QString const& componentDeclaration, QSharedPointer<Component> targetComponent)
    {
        // Paint the text black.
        highlighter_->applyFontColor(input, QColor("black"));
    
        // Highlight the matching part of the text.
        highlighter_->applyHighlight("input clock;", ImportColors::CLOCK);
    
        // Find the beginning and the end of the name.
        int moduleNameBegin = input.indexOf("name");
        int moduleNameEnd = moduleNameBegin + 4;
        // Highlight the name.
        highlighter_->applyHighlight(moduleNameBegin, moduleNameEnd, ImportColors::VIEWNAME);
    }

class IGeneratorPlugin

Generator plugins can be used in the component editor and design editors to generate content for the currently active document. The content can be, e.g., new source files or direct modifications to the IP-XACT metadata of the document. Plugin generators will automatically appear in the Kactus2 ribbon menu under the Generation group.

Functions:

  • virtual QIcon getIcon(): Returns the icon that will be shown in the Kactus2 ribbon menu for the generator.

  • virtual bool checkGeneratorSupport(): Checks whether the generator may run for the given component or design.

    • Parameters:
    • QSharedPointer<Component const> component: The component for which to check support. If design is not null, component will refer to design or designConfiguration.
    • QSharedPointer<Design const> design: The design, if the generator is ran for a design.
    • QSharedPointer<DesignConfiguration const> designConfiguration: The design configuration for design, if it is not null.
    • Returns: True, if the generator may run the given component or design. Otherwise false.
  • virtual void runGenerator(): Runs the generation, creating new files and/or modifying the IP-XACT metadata. The function has also access to the parent window widget, so that it can show dialogs for the user to aid the generation.

    • Parameters:
    • IPluginUtility* utility: The plugin utility interface.
    • QSharedPointer<Component> component: The component for which to check support. If design is not null, component will refer to design or designConfiguration.
    • QSharedPointer<Design> design: The design, if the generator is ran for a design.
    • QSharedPointer<DesignConfiguration> designConfiguration: The design configuration for design, if it is not null.

Example of a generator plugin class definition:

    #include <KactusAPI/include/IGeneratorPlugin.h>
    #include <KactusAPI/include/IPluginUtility.h>
    
    class MAKEFILEGENERATOR_EXPORT MakefileGeneratorPlugin : public QObject, public IGeneratorPlugin
    {
        Q_OBJECT
        // Explained at http://doc.qt.io/qt-6.2/qtplugin.html#Q_PLUGIN_METADATA
        Q_PLUGIN_METADATA(IID "kactus2.plugins.MakefileGenerator" FILE "makefile.json")
    
        Q_INTERFACES(IPlugin)
        Q_INTERFACES(IGeneratorPlugin)
    
    public:
        ...
    };

class IPluginUtility

IPluginUtility offers core utilities for plugins, namely access to the console, the parent widget, and most importantly the IP-XACT library. It is provided for a plugin via the implemented plugin interface.

Functions:

  • virtual LibraryInterface* getLibraryInterface(): Returns the library interface.

  • virtual QWidget* getParentWidget(): Returns the parent widget to be used for e.g. dialogs.

  • virtual QString getKactusVersion(): Returns the current version of the Kactus2 build.

  • virtual void printError(): Prints an error message to the console window. The message is shown in red color.

    • Parameters:
    • QString const& message: The error message to print.
  • virtual void printInfo(): Prints an info message to the console window.

    • Parameters:
    • QString const& message: The info message to print.

Example usage:

    void SampleGeneratorPlugin::runGenerator( IPluginUtility* utility, 
        QSharedPointer<Document> libComp,
        QSharedPointer<Document> libDesConf,
        QSharedPointer<Document> libDes)
    {
        // Acquire the path of the top component via the library interface of the utility.
        QString targetDir = QFileInfo(utility->getLibraryInterface()->getPath(libComp->getVlnv())).absolutePath(); 
    
        // If it is empty, report an error via utility and return.
        if ( targetDir.isEmpty() )
        {
            utility->printError( "Must not generate to non-existing folder." );
            return;
        }
    
        // Now we can generate.
        generate( targetDir, utility );
    
        // Finally, inform via utility that the generation is complete.
        utility->printInfo( "Sample generation complete." );
    }

class LibraryInterface

LibraryInterface defines an interface to operate the IP-XACT-library.

  • virtual QSharedPointer<Document> getModel(): Get a document that matches given VLNV. Must be used when changes are made to the document. The provided document is a copy, meaning that it must be explicitly saved after the changes.

    • Parameters:
    • VLNV const& vlnv: Identifies the desired document.
    • Returns: The model that matches the document.
  • virtual QSharedPointer<Document const> getModelReadOnly(): Get a document that matches given VLNV for read-only access. May be used when no changes are to be made for the document.

    • Parameters:
    • VLNV const& vlnv: Identifies the desired document.
    • Returns: The model that matches the document.
  • virtual bool contains(): Checks if the library already contains the specified VLNV.

    • Parameters:
    • VLNV const& vlnv: The VLNV that is searched within the library.
    • Returns: True if the VLNV was found, otherwise false.
  • virtual QList<VLNV> getAllVLNVs(): Gets all the VLNVs currently in the library.

  • virtual const QString getPath(): Get a path to the specified IP-XACT document.

    • Parameters:
    • VLNV const& vlnv: Specifies the wanted IP-XACT document.
    • Returns: The path to the document. If VLNV is not found then empty string is returned.
  • virtual QString getDirectoryPath(): Get the directory path to the specified IP-XACT document.

    • Parameters:
    • VLNV const& vlnv: Specifies the wanted IP-XACT document.
    • Returns: The directory path to the document. Does not contain the XML file name.
  • virtual bool writeModelToFile(): Write a document to file system to given file path. If file already exists in file system it is overwritten.

    • Parameters:
    • QString const& path: Directory path that specifies the directory to save to file into. The path must not contain the file name.
    • QSharedPointer<Document> model: The document that is written.
    • Returns: True if the model was in valid state and was successfully written.
  • virtual void searchForIPXactFiles(): Search for IP-XACT files in the file system and add them to library.

  • virtual void getNeededVLNVs(): Get list of VLNVs that are needed by given document. This function takes an IP-XACT document and searches it and returns list of all vlnvs that are needed by that document. Function also searches all possible sub VLNVs that need other vlnvs and adds them to the list. The list doesn't contain single VLNV twice.

    • Parameters:
    • VLNV const& vlnv: The vlnv that is used as starting point for the search.
    • QList<VLNV>& list: The list where all VLNVs are added to.
  • virtual void getDependencyFiles(): Get list of files that are needed by the given document. This function returns a list of file paths that are converted as absolute file paths to the needed files. This function searches files only from this document, it does not search possible subcomponents.

    • Parameters:
    • VLNV const& vlnv: The vlnv that is used for the search.
    • QStringList& list: The files are appended to the list if they are not already on the list.
  • virtual LibraryItem const* getTreeRoot(): Get the root item of the library tree.

  • virtual VLNV::IPXactType getDocumentType(): Get the document type of given vlnv.

    • Parameters:
    • VLNV const& vlnv: Specifies the document that's type is wanted.
    • Returns: The type of the document.
  • virtual int referenceCount(): Count how many times the given component is instantiated in the library.

    • Parameters:
    • VLNV const& vlnv: Identifies the component that's instances are searched.
    • Returns: Number of found instances.
  • virtual int getOwners(): Get the components that have instantiated the given vlnv in their design.

    • Parameters:
    • QList<VLNV>& list: The search results.
    • VLNV const& vlnvToSearch: Identifies the component to search for.
    • Returns: Number of found instances.
  • virtual int getChildren(): Get the items that are needed by the specified item.

    • Parameters:
    • QList<VLNV>& list: The search results.
    • VLNV const& vlnvToSearch: Identifies the item thats child-items are wanted.
    • Returns: Number of found instances.
  • virtual int getDesignVLNV(): Get the VLNV of the design for a given hierarchy reference. This function can be used by calling it with a hierarchy reference found in a component's hierarchical view. Function checks if the reference is directly for a design and returns the design VLNV. If reference is for a configuration then the design VLNV is searched from the configuration and design VLNV is returned. If design is not found then invalid VLNV is returned.

    • Parameters:
    • VLNV const& hierarchyRef: The hierarchical reference obtained from component's view.
    • Returns: The VLNV identifying the design object.
  • virtual QSharedPointer<Design> getDesign(): Get the design for a given hierarchy reference. This function can be used by calling it with a hierarchy reference found if a component's hierarchical view. Function checks if the reference is directly for a design and returns the design pointer. If reference is for a configuration then the design VLNV is searched from the configuration and design pointer is returned. If design is not found then null pointer is returned.

    • Parameters:
    • VLNV const& hierarchyRef: The hierarchical reference obtained from component's view.
    • Returns: The design.
  • virtual bool isValid(): Check if the identified object is in valid state.

    • Parameters:
    • VLNV const& vlnv: Identifies the object to check.
    • Returns: True if the object was valid. False if invalid or object was not found in library.

Example usage:

    for (QSharedPointer<ComponentInstance> instance : *design->getComponentInstances())
    {
        // Component instance knows which component it is instantiating.
        QSharedPointer<VLNV> vlnv = instance->getComponentRef();
        // Get component by VLNV.
        QSharedPointer<Document> doc = library->getModel(*vlnv);
        QSharedPointer<Component> component = doc.dynamicCast<Component>();
    
        // Add a new fileset called "FileSetName".
        QSharedPointer<FileSet> fileSet = QSharedPointer<FileSet>(new FileSet("FileSetName", "FileSetGroup"));
        component->getFileSets()->append(fileSet);
    
        // Must write the component again, because changes were made.
        utility->getLibraryInterface()->writeModelToFile(doc);
    }