> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/opentrack/opentrack/llms.txt
> Use this file to discover all available pages before exploring further.

# Metadata Interface

> Plugin metadata and registration requirements

## Overview

Every OpenTrack plugin must provide metadata through the `Metadata` class. This includes the plugin's display name and icon that appear in the user interface.

## Interface Definition

```cpp theme={null}
class Metadata : public TR, public Metadata_
{
    Q_OBJECT
public:
    Metadata();
    ~Metadata() override;
    
    virtual QString name() = 0;  // Plugin display name
    virtual QIcon icon() = 0;    // Plugin icon
};
```

## Base Classes

### Metadata\_

```cpp theme={null}
class OTR_API_EXPORT Metadata_
{
public:
    Metadata_();
    virtual ~Metadata_();
    
    virtual QString name() = 0;
    virtual QIcon icon() = 0;
};
```

The base interface that defines the required methods.

### TR

Provides translation support through Qt's internationalization system. Inherit from this to enable `tr()` function for translatable strings.

## Methods

### name()

```cpp theme={null}
virtual QString name() = 0;
```

Returns the human-readable name of the plugin.

<ResponseField name="return" type="QString">
  The plugin name displayed in the UI dropdown menus
</ResponseField>

**Guidelines:**

* Use descriptive, user-friendly names
* Keep names concise (prefer "Easy Tracker" over "Easy Tracker Version 1.1")
* Use `tr()` for internationalization support
* Include version numbers only if multiple versions exist

**Examples:**

<CodeGroup>
  ```cpp tracker-easy/module.cpp theme={null}
  QString Metadata::name() 
  { 
      return tr("Easy Tracker 1.1"); 
  }
  ```

  ```cpp proto-ft/ftnoir_protocol_ft.h theme={null}
  QString name() 
  { 
      return tr("freetrack 2.0 Enhanced"); 
  }
  ```

  ```cpp filter-accela/ftnoir_filter_accela.h theme={null}
  QString name() 
  { 
      return tr("Accela"); 
  }
  ```
</CodeGroup>

### icon()

```cpp theme={null}
virtual QIcon icon() = 0;
```

Returns the plugin's icon for display in the UI.

<ResponseField name="return" type="QIcon">
  A QIcon object, or empty icon if none available
</ResponseField>

**Guidelines:**

* Use 16x16 or 32x32 PNG images for best results
* Store icons in Qt resource files (`.qrc`)
* Return `QIcon()` (empty) if no icon available
* Use consistent icon style within plugin family

**Icon resource setup:**

1. **Create resource file** (`plugin.qrc`):

```xml theme={null}
<RCC>
    <qresource prefix="/">
        <file>Resources/icon.png</file>
    </qresource>
</RCC>
```

2. **Add to CMakeLists.txt**:

```cmake theme={null}
opentrack_boilerplate(
    opentrack-tracker-myplugin
    SOURCES tracker.cpp tracker.h
    RESOURCES plugin.qrc
)
```

3. **Reference in code**:

```cpp theme={null}
QIcon icon() override 
{ 
    return QIcon(":/Resources/icon.png"); 
}
```

**Examples:**

<CodeGroup>
  ```cpp With Icon theme={null}
  QIcon icon() override
  {
      return QIcon(":/images/filter-16.png");
  }
  ```

  ```cpp Without Icon theme={null}
  QIcon icon() override
  {
      return QIcon();  // Empty icon
  }
  ```

  ```cpp Embedded Resource theme={null}
  QIcon icon() override
  {
      return QIcon(":/Resources/easy-tracker-logo.png");
  }
  ```
</CodeGroup>

## Complete Implementation

<CodeGroup>
  ```cpp Header File theme={null}
  #pragma once
  #include "api/plugin-api.hpp"

  class MyTrackerMetadata : public Metadata
  {
      Q_OBJECT
  public:
      QString name() override { return tr("My Tracker"); }
      QIcon icon() override { return QIcon(":/images/mytracker.png"); }
  };
  ```

  ```cpp Separate Implementation theme={null}
  class MyTrackerMetadata : public Metadata
  {
      Q_OBJECT
  public:
      QString name() override;
      QIcon icon() override;
  };

  // In .cpp file
  QString MyTrackerMetadata::name()
  {
      return tr("My Tracker");
  }

  QIcon MyTrackerMetadata::icon()
  {
      return QIcon(":/images/mytracker.png");
  }
  ```
</CodeGroup>

## Plugin Registration

The metadata class is used in plugin registration macros:

### Tracker Registration

```cpp theme={null}
OPENTRACK_DECLARE_TRACKER(tracker_class, dialog_class, metadata_class)
```

**Example:**

```cpp theme={null}
OPENTRACK_DECLARE_TRACKER(EasyTracker::Tracker, 
                          EasyTracker::Dialog, 
                          EasyTracker::Metadata)
```

### Protocol Registration

```cpp theme={null}
OPENTRACK_DECLARE_PROTOCOL(protocol_class, dialog_class, metadata_class)
```

**Example:**

```cpp theme={null}
OPENTRACK_DECLARE_PROTOCOL(freetrack, 
                           FTControls, 
                           freetrackDll)
```

### Filter Registration

```cpp theme={null}
OPENTRACK_DECLARE_FILTER(filter_class, dialog_class, metadata_class)
```

**Example:**

```cpp theme={null}
OPENTRACK_DECLARE_FILTER(accela, 
                         dialog_accela, 
                         accelaDll)
```

## Registration Macro Details

### What the Macros Do

The registration macros expand to export three C functions:

```cpp theme={null}
extern "C"
{
    OTR_PLUGIN_EXPORT ITracker* GetConstructor(void);
    OTR_PLUGIN_EXPORT Metadata_* GetMetadata(void);
    OTR_PLUGIN_EXPORT ITrackerDialog* GetDialog(void);
}
```

These functions are called by OpenTrack to:

1. **GetMetadata()**: Query plugin name/icon for UI display
2. **GetConstructor()**: Create plugin instance when selected
3. **GetDialog()**: Create settings dialog when configured

### Macro Definition

```cpp theme={null}
#define OPENTRACK_DECLARE_PLUGIN_INTERNAL(ctor_class, ctor_ret_class, \
                                          metadata_class, dialog_class, \
                                          dialog_ret_class) \
    extern "C" \
    { \
        OTR_PLUGIN_EXPORT ctor_ret_class* GetConstructor(void) \
        { \
            return new ctor_class; \
        } \
        OTR_PLUGIN_EXPORT Metadata_* GetMetadata(void) \
        { \
            return new metadata_class; \
        } \
        OTR_PLUGIN_EXPORT dialog_ret_class* GetDialog(void) \
        { \
            return new dialog_class; \
        } \
    }
```

## Example Metadata Classes

<Tabs>
  <Tab title="Tracker">
    ```cpp theme={null}
    namespace EasyTracker
    {
        class Metadata : public ::Metadata
        {
            Q_OBJECT
        public:
            QString name() override 
            { 
                return tr("Easy Tracker 1.1"); 
            }
            
            QIcon icon() override 
            { 
                return QIcon(":/Resources/easy-tracker-logo.png"); 
            }
        };
    }

    OPENTRACK_DECLARE_TRACKER(EasyTracker::Tracker,
                              EasyTracker::Dialog,
                              EasyTracker::Metadata)
    ```
  </Tab>

  <Tab title="Protocol">
    ```cpp theme={null}
    class freetrackDll : public Metadata
    {
        Q_OBJECT
    public:
        QString name() override 
        { 
            return tr("freetrack 2.0 Enhanced"); 
        }
        
        QIcon icon() override 
        { 
            return QIcon(":/images/freetrack.png"); 
        }
    };

    OPENTRACK_DECLARE_PROTOCOL(freetrack,
                               FTControls,
                               freetrackDll)
    ```
  </Tab>

  <Tab title="Filter">
    ```cpp theme={null}
    class accelaDll : public Metadata
    {
        Q_OBJECT
    public:
        QString name() override 
        { 
            return tr("Accela"); 
        }
        
        QIcon icon() override 
        { 
            return QIcon(":/images/filter-16.png"); 
        }
    };

    OPENTRACK_DECLARE_FILTER(accela,
                             dialog_accela,
                             accelaDll)
    ```
  </Tab>
</Tabs>

## Translation Support

To support multiple languages, use Qt's translation system:

### 1. Mark Strings for Translation

```cpp theme={null}
QString name() override
{
    return tr("My Plugin");  // Translatable
}
```

### 2. Create Translation Files

Create `.ts` files for each language:

```xml theme={null}
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="de_DE">
    <context>
        <name>MyPluginMetadata</name>
        <message>
            <source>My Plugin</source>
            <translation>Mein Plugin</translation>
        </message>
    </context>
</TS>
```

### 3. Add to Build System

```cmake theme={null}
opentrack_boilerplate(
    opentrack-tracker-myplugin
    SOURCES tracker.cpp
    TRANSLATIONS lang/de_DE.ts lang/fr_FR.ts
)
```

## Best Practices

<AccordionGroup>
  <Accordion title="Naming Conventions">
    * **Be descriptive**: "Point Tracker" not "PT"
    * **User-friendly**: "Easy Tracker" not "tracker-easy"
    * **Consistent**: Match naming style of existing plugins
    * **Versioned**: Include version if multiple versions exist

    ```cpp theme={null}
    // Good
    return tr("Easy Tracker 1.1");
    return tr("Accela");

    // Less good
    return tr("tracker_easy_v1");
    return tr("ACCELA_FILTER");
    ```
  </Accordion>

  <Accordion title="Icon Guidelines">
    * **Size**: 16x16 or 32x32 pixels
    * **Format**: PNG with transparency
    * **Style**: Simple, recognizable shapes
    * **Color**: Match OpenTrack's color scheme
    * **Fallback**: Return empty QIcon() if none available

    ```cpp theme={null}
    // Prefer embedded resources
    QIcon icon() override
    {
        return QIcon(":/images/icon.png");
    }

    // OK to have no icon
    QIcon icon() override
    {
        return QIcon();
    }
    ```
  </Accordion>

  <Accordion title="Class Naming">
    * Metadata class can have any name
    * Common patterns:
      * `<PluginName>Metadata`
      * `<PluginName>Dll` (legacy)
      * `Metadata` in plugin namespace

    ```cpp theme={null}
    // Pattern 1: Suffixed
    class MyTrackerMetadata : public Metadata { };

    // Pattern 2: Legacy style
    class myTrackerDll : public Metadata { };

    // Pattern 3: Namespaced
    namespace MyTracker {
        class Metadata : public ::Metadata { };
    }
    ```
  </Accordion>
</AccordionGroup>

## Common Issues

<Warning>
  Common pitfalls when implementing metadata:
</Warning>

### Missing Q\_OBJECT Macro

```cpp theme={null}
// WRONG: Missing Q_OBJECT
class MyMetadata : public Metadata
{
public:
    QString name() override { return "My Plugin"; }
};

// CORRECT: Includes Q_OBJECT
class MyMetadata : public Metadata
{
    Q_OBJECT  // Required for Qt meta-object system
public:
    QString name() override { return "My Plugin"; }
};
```

### Not Using tr() for Translation

```cpp theme={null}
// WRONG: Hard-coded string
QString name() override { return "My Plugin"; }

// CORRECT: Translatable string
QString name() override { return tr("My Plugin"); }
```

### Invalid Icon Path

```cpp theme={null}
// WRONG: File path instead of resource path
QIcon icon() override { return QIcon("images/icon.png"); }

// CORRECT: Qt resource path
QIcon icon() override { return QIcon(":/images/icon.png"); }
```

## See Also

* [Plugin API Overview](/api/overview) - Plugin system architecture
* [Tracker Interface](/api/tracker-interface) - Tracker plugin interface
* [Protocol Interface](/api/protocol-interface) - Protocol plugin interface
* [Filter Interface](/api/filter-interface) - Filter plugin interface
