// Copyright (C) 2021 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only

/*!
    \page first-plugin.html
    \title Creating C++-Based Plugins

    This topic describes how to create a C++-based \QC plugin and get the first
    impression of its contents and structure.

    \section1 Creating a C++ Plugin Project

    \QC comes with a wizard for \QC C++ plugins, that creates a runable, \e minimal
    plugin for you. We strongly suggest that you use two different \QC instances
    for developing and testing your plugin with. Otherwise your plugin will also
    be loaded in your development environment, which can make that unstable
    while your plugin is still unstable. You can just create a copy of your \QC
    build and use one for actually developing, and the other for testing your
    plugin with.

    You need to make sure that you use the same \QC version that you want to
    develop for to create the plugin. Because of the \l{Binary and Source
    Compatibility} rules of \QC, the \QC plugin wizard creates a plugin that
    might only compile and run with the same \QC version that it was created
    with.

    \list 1
        \li Select \uicontrol File > \uicontrol {New Project} >
            \uicontrol Library > \uicontrol {\QC C++ Plugin} >
            \uicontrol Choose.

            \image firstplugin-wizard.png "Choose the \QC C++ Plugin Wizard"

            The \uicontrol{Introduction and Project Location} dialog opens.

            \image firstplugin-nameandpath.png "Choose Name and Place of the Project"

        \li Give your project a name and specify in which path this project will
            be created. The actual plugin's name can be different from the
            project name. You will choose that name later in the wizard.

        \li Continue to the \uicontrol {Plugin Information} dialog.

            \image firstplugin-pluginsetup.png "Specify Your Plugin Details"

        \li In the \uicontrol {Plugin name} field, type \uicontrol Example. The
            name of the plugin is used as its identifier, and also is the base
            for the file names and classes in the code.

        \li The values of the following fields are mainly informational, and
            are shown in the detailed view in \QC's plugin overview
            (\uicontrol Help > \uicontrol {About Plugins}, or
            \uicontrol {\QC} > \uicontrol {About Plugins} on \macos).

            \list
                \li \uicontrol {Vendor name} is a short one-word name of the
                    company or organization that created the plugin. This is
                    also used for the path name where the plugin will be
                    deployed to.

                \li \uicontrol Copyright is a one-line, short copyright string.

                \li \uicontrol License is a license text.

                \li \uicontrol{Description} is a short description of what the
                    plugin does.

                \li \uicontrol URL is a website where the user can find more
                    information about the plugin and/or organization providing
                    it.
           \endlist

        \li Set the \uicontrol{\QC build} field to the build directory
            of the \QC instance you want to use to test your plugin with. If
            you don't do that correctly, you will get compile errors for your
            plugin, and your plugin might not show up in \QC at all.

        \li Continue to the \uicontrol {Translation File} dialog.

            \image firstplugin-translation-file.png "Choose a language to localize your plugin to"

        \li Select a language to localize your plugin to. This sets up
            translation support for the selected language.

        \li Continue to the \uicontrol {Kit Selection} dialog.

            \image firstplugin-kitselection.png "Choose the kit to build and run your project with"

        \li Select the kit to build and run your project with. For a \QC plugin,
            this needs to be a kit with \uicontrol Desktop device type, and a Qt
            version that is compatible with the Qt version that your \QC was
            built with (in the best case the exact same build). If you use an
            incompatible Qt version to build your plugin, you will get errors
            while \QC tries to load your plugin.

        \li Continue to the \uicontrol {Project Management} dialog.

            \image firstplugin-summary.png "Summary of Created Files"

        \li Review the files that will be created, choose a version control
            system that \QC should use for your project (always a good idea!),
            and finish the wizard.
    \endlist

    \section1 Building and Running the Plugin

    If you passed the correct \QC build path in the project wizard,
    your plugin should just build fine when pressing the build button. Before
    running the project, select \uicontrol {Build & Run} > \uicontrol Run to
    specify run settings:

    \image firstplugin-runsettings.png "Specify the Executable to Run"

    Select the path to the \QC executable from the build that you specified in
    the \uicontrol {\QC build} field in the project wizard and set the value
    of the \uicontrol {Command line arguments} field to
    \c {-pluginpath %{buildDir}}.

    When you select \uicontrol OK, \QC starts up, and you can verify that your
    plugin is successfully loaded by looking for a menu entry \uicontrol Tools >
    \uicontrol Example and by looking for the plugin in the \uicontrol Help >
    \uicontrol {About Plugins} dialog.

    \section1 File Structure

    The plugin wizard creates a set of basic files that a plugin needs or should
    have. We will have a look at some of them in detail in the following
    sections, here is a short overview:

    \table
    \header
        \li File

        \li Role
    \row
        \li \c {README.md}

        \li Describes how to build and run the plugin.
    \row
        \li \c {Example.json.in}

        \li Plugin meta data template. CMake creates an \c {Example.json}
            from this file, which is compiled into the plugin as meta data.
            The meta data is read by \QC to find out about the plugin.
    \row
        \li \c {CMakeLists.txt}

        \li Project file, used by CMake to generate build files and build the plugin.
    \row
        \li \c {example_global.h}

        \li Contains macro definitions that are useful when this plugin should export
            symbols to other plugins.
    \row
        \li \c {exampleconstants.h}

        \li Header defining constants used by the plugin code.
    \row
        \li \c{example.h, example.cpp}

        \li C++ header and source files that define the plugin class that will be
            instantiated and run by \QC's plugin manager.
    \row
        \li \c{build_cmake.yml}

        \li Adds a \l {GitHub Actions}{GitHub action} and workflow that builds
            your plugin anytime you
            push commits to GitHub on Windows, Linux, and macOS. For more
            information, see \c {.github\workflow\README.md}.
    \endtable

    \section1 CMake Project

    The CMake project file \c {CMakeLists.txt} defines how your plugin should be
    compiled. \QC plugins need to have a specific setup there, in addition to
    telling CMake which files need to be compiled (or handled by \c moc or
    \c uic). Let us have a look at what the project wizard generated for you in
    detail.

    \snippet exampleplugin/CMakeLists.txt 1

    The \c{list(APPEND ...)} call tells CMake to include the \QC build path that
    you specified in the wizard in its search path for dependencies. Since this
    contains an absolute path on your local machine, you should remove this line
    when sharing the project with others.

    Without this line, you need to explicitly add the path to the \QC
    build to \c {CMAKE_PREFIX_PATH} when configuring your plugin with CMake.

    \snippet exampleplugin/CMakeLists.txt 2

    This section does some standard setup for Qt/CMake projects. Besides
    setting a project name and a C++ standard to use, it turns on automatic
    detection of files that need to be run through \c {moc}, \c {rcc} or \c
    {uic}.

    \snippet exampleplugin/CMakeLists.txt 3

    This section tells CMake to locate \QC and Qt. If your plugin requires
    additional Qt modules, you need to add them to the corresponding
    \c {find_package} call in this section.

    To find \QC and Qt, the paths to the \QC and Qt installation must be
    present in the \c {CMAKE_PREFIX_PATH} when you configure your plugin
    with CMake.

    \snippet exampleplugin/CMakeLists.txt 4

    The \c {add_qtc_plugin} call creates a target for your plugin with the
    specified name.

    In the \c {PLUGIN_DEPENDS} sub-section, you need to specify \QC plugins that
    your plugin depends on. Valid values are a plugin's name prefixed with
    \c {QtCreator::}.

    In the \c {DEPENDS} sub-section, you need to specify libraries that your
    plugin depends on. Use a Qt module name prefixed with \c {$\{QtX\}::}
    to link to additional Qt modules. To link against additional \QC libraries,
    prefix their name with \c {QtCreator::}. In this subsection you also
    specify other libraries that your plugin depends on.

    In the \c {SOURCES} sub-section, you specify all files that belong to your
    plugin project. CMake sorts these into source files and header files
    automatically. Other files in this section are ignored by CMake but appear
    for example in the project tree that is shown in IDEs like \QC for easier
    access.

    \section1 Plugin Meta Data Template

    The \c {.json} file is a JSON file that contains information that is needed
    by the plugin manager to find your plugin and resolve its dependencies
    before actually loading your plugin's library file. We will only have a
    short look at it here. For more information, see \l{Plugin Meta Data}.

    The wizard doesn't actually create a .json file directly, but instead a
    \c {.json.in} file. qmake uses this to generate the actual plugin .json
    meta data file, replacing variables like \c {QTCREATOR_VERSION} with their
    actual values. Therefore you need to escape all backslashes and quotes in
    the \c {.json.in} file (i.e. you need to write \c {\} to get a backslash
    and \c{\"} to get a quote in the generated plugin JSON meta data).

    \snippet exampleplugin/Example.json.in 1

    The first items in the meta data that is created by the wizard define the
    name of your plugin, its version, and with what version of this plugin the
    current version is binary compatible with.

    \snippet exampleplugin/Example.json.in 2

    After that you'll find the information about the plugin that you gave in the
    project wizard.

    \snippet exampleplugin/Example.json.in 3

    The \c {IDE_PLUGIN_DEPENDENCIES} variable is automatically replaced by the
    dependency information in \c {PLUGIN_DEPENDS} amd \c {PLUGIN_RECOMMENDS}
    from your plugin's \c {add_qtc_plugin()} call in its \c {CMakeLists.txt} file.

    \section1 Plugin Class

    The files \c {example.h} and \c {example.cpp} define the plugin
    implementation of your little plugin. We'll concentrate on some highlights
    here, and give pointers to more detailed information for the various parts.

    \section2 Header File

    The header file \c {example.h} defines the interface of the plugin
    class.

    \snippet exampleplugin/example.h namespaces

    The plugin is defined in a \c {Example::Internal} namespace, which conforms
    to the coding rules for \l{coding-rules-namespacing}{namespacing}
    in \QC sources.

    \snippet exampleplugin/example.h base class

    All \QC plugins must be derived from \l{ExtensionSystem::IPlugin} and
    are QObjects. The \c {Q_PLUGIN_METADATA} macro is necessary to create a
    valid Qt plugin. The \c IID given in the macro must be
    \c {org.qt-project.Qt.QtCreatorPlugin}, to identify it as a \QC plugin, and
    \c FILE must point to the plugin's meta data file as described in
    \l{Plugin Meta Data}.

    \snippet exampleplugin/example.h plugin functions

    The base class defines basic functions that are called during the life cycle
    of a plugin, which are here implemented for your new plugin. These functions
    and their roles are described in detail in \l{Plugin Life Cycle}.

    \snippet exampleplugin/example.h slot

    The plugin has an additional custom slot, that is used to pop up a dialog
    when the user chooses the menu item that this plugin adds.

    \section2 Source File

    The source file contains the actual implementation of the plugin, which
    registers a new menu and menu item, and opens a message box when that item
    is triggered.

    All the necessary header files from the plugin code itself, from the \c
    Core plugin, and from Qt are included in the beginning of the file. The
    setup of the menu and menu item is done in the plugin's \c initialize
    function, which is the first thing called after the plugin constructor. In
    that function, the plugin can be sure that the basic setup of plugin's that
    it depends on has been done, for example the Core plugin's \c ActionManager
    instance has been created.

    For more information about implementing the plugin interface, see the
    \l{ExtensionSystem::IPlugin} API documentation and \l{Plugin Life Cycle}.

    \snippet exampleplugin/example.cpp add action

    This part of the code creates a new \c QAction, registers it as a new
    \c Command in the action manager, and connects it to the plugin's slot. The
    action manager provides a central place where the user can assign and change
    keyboard shortcuts, and manages cases where for example a menu item should
    be directed to different plugins under different circumstances, as well as a
    few other things.

    \snippet exampleplugin/example.cpp add menu

    Here a new menu item is created, the created command added to it, and the
    menu added to the \uicontrol Tools menu in the menu bar.

    \snippet exampleplugin/example.cpp slot implementation

    This part defines the code that is called when the menu item is triggered.
    It uses the Qt API to open a message box that displays informative text and
    an \uicontrol OK button.

    \sa {Creating Lua-Based Extensions}
*/
