Warning, /frameworks/extra-cmake-modules/modules/ECMAddQtDesignerPlugin.cmake is written in an unsupported language. File is not indexed.

0001 # SPDX-FileCopyrightText: 2019 Friedrich W. H. Kossebau <kossebau@kde.org>
0002 #
0003 # SPDX-License-Identifier: BSD-3-Clause
0004 
0005 #[=======================================================================[.rst:
0006 ECMAddQtDesignerPlugin
0007 ----------------------
0008 
0009 This module provides the ``ecm_add_qtdesignerplugin`` function for generating
0010 Qt Designer plugins for custom widgets. Each of those widgets is described
0011 using a second function ``ecm_qtdesignerplugin_widget``.
0012 
0013 ::
0014 
0015   ecm_add_qtdesignerplugin(<target_name>
0016       NAME <name>
0017       WIDGETS <widgetid> [<widgetid2> [...]]
0018       LINK_LIBRARIES <lib> [<lib2> [...]]
0019       INSTALL_DESTINATION <install_path>
0020       [OUTPUT_NAME <output_name>]
0021       [DEFAULT_GROUP <group>]
0022       [DEFAULT_HEADER_CASE <SAME_CASE|LOWER_CASE|UPPER_CASE>]
0023       [DEFAULT_HEADER_EXTENSION <header_extension>]
0024       [DEFAULT_ICON_DIR <icon_dir>]
0025       [INCLUDE_FILES <include_file> [<include_file2> [...]]]
0026       [SOURCES <src> [<src2> [...]]]
0027       [COMPONENT <component>]
0028   )
0029 
0030 ``NAME`` specifies the base name to use in the generated sources.
0031 The default is <target_name>.
0032 
0033 ``WIDGETS`` specifies the widgets the plugin should support. Each widget has
0034 to be defined before by a call of ``ecm_qtdesignerplugin_widget`` with the
0035 respective <widgetid>, in a scope including the current call.
0036 
0037 ``LINK_LIBRARIES`` specifies the libraries to link against. This will be at
0038 least the library providing the widget class(es).
0039 
0040 ``INSTALL_DESTINATION`` specifies where the generated plugin binary will be
0041 installed.
0042 
0043 ``OUTPUT_NAME`` specifies the name of the plugin binary. The default is
0044 "<target_name>".
0045 
0046 ``DEFAULT_GROUP`` specifies the default group in Qt Designer where the
0047 widgets will be placed. The default is "Custom".
0048 
0049 ``DEFAULT_HEADER_CASE`` specifies how the name of the header is derived from
0050 the widget class name.  The default is "LOWER_CASE".
0051 
0052 ``DEFAULT_HEADER_EXTENSION`` specifies what file name extension is used for
0053 the header file derived from the class name.  The default is "h".
0054 
0055 ``DEFAULT_ICON_DIR`` specifies what file name extension is used for
0056 the header file derived from the class name.  The default is "pics".
0057 
0058 ``INCLUDE_FILES`` specifies additional include files to include with the
0059 generated source file. This can be needed for custom code used in
0060 initializing or creating widgets.
0061 
0062 ``SOURCES`` specifies additional source files to build the plugin from.
0063 This can be needed to support custom code used in initializing or
0064 creating widgets.
0065 
0066 ``COMPONENT`` specifies the installation component name with which the install
0067 rules for the generated plugin are associated.
0068 
0069 ::
0070 
0071   ecm_qtdesignerplugin_widget(<widgetid>
0072       [CLASS_NAME <class_name>]
0073       [INCLUDE_FILE <include_file>]
0074       [CONTAINER]
0075       [ICON <iconfile>]
0076       [TOOLTIP <tooltip>]
0077       [WHATSTHIS <whatsthis>]
0078       [GROUP <group>]
0079       [CREATE_WIDGET_CODE_FROM_VARIABLE <create_widget_code_variable>]
0080       [INITIALIZE_CODE_FROM_VARIABLE <initialize_code_variable]
0081       [DOM_XML_FROM_VARIABLE <dom_xml_variable>]
0082       [IMPL_CLASS_NAME <impl_class_name>]
0083       [CONSTRUCTOR_ARGS_CODE <constructor_args_code>]
0084       [CONSTRUCTOR_ARGS_CODE_FROM_VARIABLE <constructor_args_code_variable>]
0085   )
0086 
0087 ``CLASS_NAME`` specifies the name of the widget class, including namespaces.
0088 The default is "<widgetid>".
0089 
0090 ``INCLUDE_FILE`` specifies the include file to use for the class of this
0091 widget. The default is derived from <class_name> as configured by the
0092 ``DEFAULT_HEADER_*`` options of ``ecm_add_qtdesignerplugin``, also replacing
0093 any namespace separators with "/".
0094 
0095 ``CONTAINER`` specifies, if set, that this widget is a container
0096 for other widgets.
0097 
0098 ``ICON`` specifies the icon file to use as symbol for this widget.
0099 The default is "{lowercased <class_name>}.png" in the default icons dir as
0100 configured by the ``DEFAULT_ICON_DIR`` option of
0101 ``ecm_add_qtdesignerplugin``, if such a file exists.
0102 
0103 ``TOOLTIP`` specifies the tooltip text to use for this widget. Default is
0104 "<class_name> Widget".
0105 
0106 ``WHATSTHIS`` specifies the What's-This text to use for this widget.
0107 Defaults to the tooltip.
0108 
0109 ``GROUP`` specifies the group in Qt Designer where the widget will be placed.
0110 The default is set as configured by the ``DEFAULT_GROUP`` option of
0111 ``ecm_add_qtdesignerplugin``.
0112 
0113 ``CREATE_WIDGET_CODE_FROM_VARIABLE`` specifies the variable to get from the
0114 C++ code to use as factory code to create an instance of the widget,
0115 for the override of
0116 ``QDesignerCustomWidgetInterface::createWidget(QWidget* parent)``.
0117 The default is "return new <impl_class_name><constructor_args_code>;".
0118 
0119 ``INITIALIZE_CODE_FROM_VARIABLE`` specifies the variable to get from the C++
0120 code to use with the override of
0121 ``QDesignerCustomWidgetInterface::initialize(QDesignerFormEditorInterface* core)``.
0122 The code has to use the present class member ``m_initialized`` to track and
0123 update the state. The default code simply sets ``m_initialized`` to
0124 ``true``, if it was not before.
0125 
0126 ``DOM_XML_FROM_VARIABLE`` specifies the variable to get from the string to
0127 use with the optional override of
0128 ``QDesignerCustomWidgetInterface::domXml()``.
0129 Default does not override.
0130 
0131 ``IMPL_CLASS_NAME`` specifies the name of the widget class to use for the
0132 widget instance with Qt Designer. The default is "<class_name>".
0133 
0134 ``CONSTRUCTOR_ARGS_CODE`` specifies the C++ code to use for the constructor
0135 arguments with the default of ``CREATE_WIDGET_CODE_FROM_VARIABLE``. Note
0136 that the parentheses are required. The default is "(parent)".
0137 
0138 ``CONSTRUCTOR_ARGS_CODE_FROM_VARIABLE`` specifies the variable to get from
0139 the C++ code instead of passing it directly via ``CONSTRUCTOR_ARGS_CODE``.
0140 This can be needed if the code is more complex and e.g. includes ";" chars.
0141 
0142 
0143 
0144 Example usage:
0145 
0146 .. code-block:: cmake
0147 
0148   ecm_qtdesignerplugin_widget(FooWidget
0149       TOOLTIP "Enables to browse foo."
0150       GROUP "Views (Foo)"
0151   )
0152 
0153   set(BarWidget_CREATE_WIDGET_CODE
0154   "
0155       auto* widget = new BarWidget(parent);
0156       widget->setBar("Example bar");
0157       return widget;
0158   ")
0159 
0160   ecm_qtdesignerplugin_widget(BarWidget
0161       TOOLTIP "Displays bars."
0162       GROUP "Display (Foo)"
0163       CREATE_WIDGET_CODE_FROM_VARIABLE BarWidget_CREATE_WIDGET_CODE
0164   )
0165 
0166   ecm_add_qtdesignerplugin(foowidgets
0167       NAME FooWidgets
0168       OUTPUT_NAME foo2widgets
0169       WIDGETS
0170           FooWidget
0171           BarWidget
0172       LINK_LIBRARIES
0173           Foo::Widgets
0174       INSTALL_DESTINATION "${KDE_INSTALL_QTPLUGINDIR}/designer"
0175       COMPONENT Devel
0176   )
0177 
0178 Since 5.62.0.
0179 #]=======================================================================]
0180 
0181 include(FeatureSummary)
0182 include(${CMAKE_CURRENT_LIST_DIR}/QtVersionOption.cmake)
0183 
0184 # helper method
0185 # escapes string for C++ code
0186 function(_ecm_qtdesignerplugin_escape_cpp_string _varName input)
0187     string(REPLACE "\"" "\\\"" _string ${input})
0188     set(${_varName} "${_string}" PARENT_SCOPE)
0189 endfunction()
0190 
0191 # To make the data about the widgets available to the function ecm_add_qtdesignerplugin,
0192 # variables are created in the scope of the caller of this method, protected by
0193 # a namespace for this macro file, and otherwise from the widget id and the property id:
0194 # ECM_QTDESIGNERPLUGIN_${widget}_${property}
0195 function(ecm_qtdesignerplugin_widget widget)
0196     set(options
0197         CONTAINER
0198     )
0199     set(oneValueArgs
0200         CLASS_NAME
0201         INCLUDE_FILE
0202         ICON
0203         TOOLTIP
0204         WHATSTHIS
0205         GROUP
0206         CREATE_WIDGET_CODE_FROM_VARIABLE
0207         INITIALIZE_CODE_FROM_VARIABLE
0208         DOM_XML_FROM_VARIABLE
0209         IMPL_CLASS_NAME
0210         CONSTRUCTOR_ARGS_CODE
0211         CONSTRUCTOR_ARGS_CODE_FROM_VARIABLE
0212     )
0213     set(multiValueArgs
0214     )
0215     cmake_parse_arguments(ARGS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
0216 
0217     if(NOT ARGS_CLASS_NAME)
0218         set(ARGS_CLASS_NAME "${widget}")
0219     endif()
0220     if(NOT ARGS_TOOLTIP)
0221         set(ARGS_TOOLTIP "${ARGS_CLASS_NAME} Widget")
0222     endif()
0223     if(NOT ARGS_WHATSTHIS)
0224         set(ARGS_WHATSTHIS "${ARGS_TOOLTIP}")
0225     endif()
0226     if(ARGS_CONTAINER)
0227         set(_is_container TRUE)
0228     else()
0229         set(_is_container FALSE)
0230     endif()
0231     if(ARGS_CONSTRUCTOR_ARGS_CODE AND ARGS_CONSTRUCTOR_ARGS_CODE_FROM_VARIABLE)
0232         message(FATAL_ERROR "Either CONSTRUCTOR_ARGS_CODE or CONSTRUCTOR_ARGS_CODE_FROM_VARIABLE can be passed when calling ecm_qtdesignerplugin_widget().")
0233     endif()
0234     if(NOT ARGS_CREATE_WIDGET_CODE_FROM_VARIABLE)
0235         if(NOT ARGS_IMPL_CLASS_NAME)
0236             set(ARGS_IMPL_CLASS_NAME "${ARGS_CLASS_NAME}")
0237         endif()
0238         if(ARGS_CONSTRUCTOR_ARGS_CODE_FROM_VARIABLE)
0239             set(_constructor_args "${${ARGS_CONSTRUCTOR_ARGS_CODE_FROM_VARIABLE}}")
0240         elseif(ARGS_CONSTRUCTOR_ARGS_CODE)
0241             set(_constructor_args "${ARGS_CONSTRUCTOR_ARGS_CODE}")
0242         else()
0243             set(_constructor_args "(parent)")
0244         endif()
0245         set(_create_widget_code "        return new ${ARGS_IMPL_CLASS_NAME}${_constructor_args};")
0246     else()
0247         set(_create_widget_code "${${ARGS_CREATE_WIDGET_CODE_FROM_VARIABLE}}")
0248     endif()
0249     if(ARGS_ICON)
0250         if (NOT IS_ABSOLUTE ${ARGS_ICON})
0251             set(ARGS_ICON "${CMAKE_CURRENT_SOURCE_DIR}/${ARGS_ICON}")
0252         endif()
0253         if(NOT EXISTS "${ARGS_ICON}")
0254             message(FATAL_ERROR "No such file as passed with ICON when calling ecm_qtdesignerplugin_widget(): ${ARGS_ICON}")
0255         endif()
0256     endif()
0257 
0258     # store data about widget, so ecm_add_qtdesignerplugin can access it
0259     set(ECM_QTDESIGNERPLUGIN_${widget}_CLASS_NAME "${ARGS_CLASS_NAME}" PARENT_SCOPE)
0260     set(ECM_QTDESIGNERPLUGIN_${widget}_INCLUDE_FILE "${ARGS_INCLUDE_FILE}" PARENT_SCOPE)
0261     set(ECM_QTDESIGNERPLUGIN_${widget}_TOOLTIP "${ARGS_TOOLTIP}" PARENT_SCOPE)
0262     set(ECM_QTDESIGNERPLUGIN_${widget}_WHATSTHIS "${ARGS_WHATSTHIS}" PARENT_SCOPE)
0263     set(ECM_QTDESIGNERPLUGIN_${widget}_GROUP "${ARGS_GROUP}" PARENT_SCOPE)
0264     set(ECM_QTDESIGNERPLUGIN_${widget}_ICON "${ARGS_ICON}" PARENT_SCOPE)
0265     set(ECM_QTDESIGNERPLUGIN_${widget}_IS_CONTAINER "${_is_container}" PARENT_SCOPE)
0266     set(ECM_QTDESIGNERPLUGIN_${widget}_CREATE_WIDGET_CODE "${_create_widget_code}" PARENT_SCOPE)
0267     set(ECM_QTDESIGNERPLUGIN_${widget}_INITIALIZE_CODE "${${INITIALIZE_CODE_FROM_VARIABLE}}" PARENT_SCOPE)
0268     set(ECM_QTDESIGNERPLUGIN_${widget}_DOM_XML "${${ARGS_DOM_XML_FROM_VARIABLE}}" PARENT_SCOPE)
0269 endfunction()
0270 
0271 # helper method
0272 function(_ecm_qtdesignerplugin_write_widget designer_src_file widget default_group rc_icon_dir)
0273     # prepare data
0274     set(_classname "${ECM_QTDESIGNERPLUGIN_${widget}_CLASS_NAME}")
0275     set(_factory_classname "${_classname}QtDesignerWidgetFactory")
0276     string(REPLACE "::" "__" _factory_classname "${_factory_classname}")
0277     set(ECM_QTDESIGNERPLUGIN_${widget}_FACTORY_CLASS_NAME "${_factory_classname}" PARENT_SCOPE)
0278     if(ECM_QTDESIGNERPLUGIN_${widget}_IS_CONTAINER)
0279         set(_is_container "true")
0280     else()
0281         set(_is_container "false")
0282     endif()
0283     _ecm_qtdesignerplugin_escape_cpp_string(_tooltip "${ECM_QTDESIGNERPLUGIN_${widget}_TOOLTIP}")
0284     _ecm_qtdesignerplugin_escape_cpp_string(_whatsthis "${ECM_QTDESIGNERPLUGIN_${widget}_WHATSTHIS}")
0285     set(_group ${ECM_QTDESIGNERPLUGIN_${widget}_GROUP})
0286     if(NOT _group)
0287         set(_group "${default_group}")
0288     endif()
0289     _ecm_qtdesignerplugin_escape_cpp_string(_group "${_group}")
0290     set(_dom_xml "${ECM_QTDESIGNERPLUGIN_${widget}_DOM_XML}")
0291     if(_dom_xml)
0292         string(REPLACE "\"" "\\\"" _dom_xml "${_dom_xml}")
0293         set(_dom_xml_method "    QString domXml() const override { return QStringLiteral(\"${_dom_xml}\"); }")
0294     else()
0295         set(_dom_xml_method)
0296     endif()
0297     set(_icon "${ECM_QTDESIGNERPLUGIN_${widget}_ICON}")
0298     if(_icon)
0299         get_filename_component(_icon_filename ${_icon} NAME)
0300         set(_icon_construct "QIcon(QStringLiteral(\":${rc_icon_dir}/${_icon_filename}\"))")
0301     else()
0302         set(_icon_construct "QIcon()")
0303     endif()
0304     set(_initialize_code "${ECM_QTDESIGNERPLUGIN_${widget}_INITIALIZE_CODE}")
0305     if(NOT _initialize_code)
0306         set(_initialize_code
0307 "        Q_UNUSED(core);
0308 
0309         if (m_initialized) return;
0310 
0311         m_initialized = true;"
0312         )
0313     endif()
0314 
0315     # write code
0316     file(APPEND ${designer_src_file} "
0317 class ${_factory_classname}
0318     : public QObject
0319     , public QDesignerCustomWidgetInterface
0320 {
0321     Q_OBJECT
0322     Q_INTERFACES(QDesignerCustomWidgetInterface)
0323 
0324 public:
0325     explicit ${_factory_classname}(QObject *parent = nullptr)
0326         : QObject(parent)
0327         , m_initialized(false)
0328     {}
0329 
0330     ~${_factory_classname}() override {}
0331     
0332 public: // QDesignerCustomWidgetInterface API
0333     bool isInitialized() const override { return m_initialized; }
0334 ${_dom_xml_method}
0335     bool isContainer() const override { return ${_is_container}; }
0336     QIcon icon() const override { return ${_icon_construct}; }
0337     QString group() const override { return QStringLiteral(\"${_group}\"); }
0338     QString includeFile() const override { return QStringLiteral(\"${ECM_QTDESIGNERPLUGIN_${widget}_INCLUDE_FILE}\"); }
0339     QString name() const override { return QStringLiteral(\"${_classname}\"); }
0340     QString toolTip() const override { return QStringLiteral(\"${_tooltip}\"); }
0341     QString whatsThis() const override { return QStringLiteral(\"${_whatsthis}\"); }
0342 
0343     QWidget* createWidget(QWidget* parent) override
0344     {
0345 ${ECM_QTDESIGNERPLUGIN_${widget}_CREATE_WIDGET_CODE}
0346     }
0347 
0348     void initialize(QDesignerFormEditorInterface* core) override 
0349     {
0350 ${_initialize_code}
0351     }
0352 
0353 private:
0354     bool m_initialized;
0355 };
0356 "
0357     )
0358 endfunction()
0359 
0360 # helper method
0361 function(_ecm_qtdesignerplugin_write_icon_qrc_file rc_file rc_icon_dir)
0362     set(_icons ${ARGN})
0363     file(WRITE ${rc_file}
0364 "<!DOCTYPE RCC><RCC version=\"1.0\">
0365 <!-- DO NOT EDIT! Generated from ecm_add_qtdesignerplugin() -->
0366 <qresource prefix=\"${rc_icon_dir}\">
0367 "
0368     )
0369     foreach(_icon ${_icons})
0370         get_filename_component(_icon_filename ${_icon} NAME)
0371         file(APPEND ${rc_file} "<file alias=\"${_icon_filename}\">${_icon}</file>\n")
0372     endforeach()
0373     file(APPEND ${rc_file}
0374 "</qresource>
0375 </RCC>
0376 "
0377     )
0378 endfunction()
0379 
0380 # This needs to be a macro not a function because of the nested
0381 # find_package() call, which will set some variables.
0382 macro(ecm_add_qtdesignerplugin target)
0383     set(options
0384     )
0385     set(oneValueArgs
0386         NAME
0387         OUTPUT_NAME
0388         INSTALL_DESTINATION
0389         DEFAULT_GROUP
0390         COMPONENT
0391         DEFAULT_HEADER_CASE
0392         DEFAULT_HEADER_EXTENSION
0393         DEFAULT_ICON_DIR
0394     )
0395     set(multiValueArgs
0396         WIDGETS
0397         LINK_LIBRARIES
0398         INCLUDE_FILES
0399         SOURCES
0400     )
0401     cmake_parse_arguments(ARGS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
0402 
0403     # args sanity check
0404     if (NOT ARGS_WIDGETS)
0405         message(FATAL_ERROR "No WIDGETS passed when calling ecm_add_qtdesignerplugin().")
0406     endif()
0407     foreach(_widget ${ARGS_WIDGETS})
0408         # using _CLASS_NAME as sample property to find if defined
0409         if (NOT ECM_QTDESIGNERPLUGIN_${_widget}_CLASS_NAME)
0410             message(FATAL_ERROR "Undefined widget passed when calling ecm_add_qtdesignerplugin(): ${_widget}")
0411         endif()
0412     endforeach()
0413 
0414     if(NOT ARGS_NAME)
0415         set(ARGS_NAME "${target}")
0416     endif()
0417     if(NOT ARGS_DEFAULT_GROUP)
0418         set(ARGS_DEFAULT_GROUP "Custom")
0419     endif()
0420     if(NOT ARGS_DEFAULT_HEADER_EXTENSION)
0421         set(ARGS_DEFAULT_HEADER_EXTENSION "h")
0422     endif()
0423     if(NOT ARGS_DEFAULT_HEADER_CASE)
0424         set(ARGS_DEFAULT_HEADER_CASE "LOWER_CASE")
0425     else()
0426         set(_allowed_values "LOWER_CASE" "UPPER_CASE" "SAME_CASE")
0427         list(FIND _allowed_values "${ARGS_DEFAULT_HEADER_CASE}" _index)
0428         if(_index EQUAL "-1")
0429             message(FATAL_ERROR "Unexpected value for DEFAULT_HEADER_CASE argument to ecm_add_qtdesignerplugin(): ${ARGS_DEFAULT_HEADER_CASE}")
0430         endif()
0431     endif()
0432     if(NOT ARGS_DEFAULT_ICON_DIR)
0433         set(ARGS_DEFAULT_ICON_DIR "${CMAKE_CURRENT_SOURCE_DIR}/pics")
0434     else()
0435         if (NOT IS_ABSOLUTE ${ARGS_DEFAULT_ICON_DIR})
0436             set(ARGS_DEFAULT_ICON_DIR "${CMAKE_CURRENT_SOURCE_DIR}/${ARGS_DEFAULT_ICON_DIR}")
0437         endif()
0438         if(NOT EXISTS "${ARGS_DEFAULT_ICON_DIR}")
0439             message(FATAL_ERROR "No such directory as passed with DEFAULT_ICON_DIR when calling ecm_add_qtdesignerplugin(): ${ARGS_DEFAULT_ICON_DIR}")
0440         endif()
0441     endif()
0442 
0443     # Check deps
0444     if(NOT Qt${QT_MAJOR_VERSION}UiPlugin_FOUND)
0445         find_package(Qt${QT_MAJOR_VERSION}UiPlugin QUIET CONFIG)
0446         set_package_properties(Qt${QT_MAJOR_VERSION}UiPlugin PROPERTIES
0447             PURPOSE "Required to build Qt Designer plugins"
0448             TYPE REQUIRED
0449         )
0450     endif()
0451 
0452     # setup plugin only if uiplugin lib was found, as we do not abort hard the cmake run otherwise
0453     if (Qt${QT_MAJOR_VERSION}UiPlugin_FOUND)
0454         set(_generation_dir "${CMAKE_CURRENT_BINARY_DIR}/${target}_ECMQtDesignerPlugin")
0455         file(MAKE_DIRECTORY "${_generation_dir}")
0456         set(_rc_icon_dir "/${ARGS_NAME}/designer")
0457 
0458         # process defaults for widgets
0459         foreach(_widget ${ARGS_WIDGETS})
0460             set(_class_name "${ECM_QTDESIGNERPLUGIN_${_widget}_CLASS_NAME}")
0461             # include file
0462             set(_include_file "${ECM_QTDESIGNERPLUGIN_${_widget}_INCLUDE_FILE}")
0463             if(NOT _include_file)
0464                 set(_include_file "${_class_name}")
0465                 if (ARGS_DEFAULT_HEADER_CASE STREQUAL "LOWER_CASE")
0466                     string(TOLOWER "${_include_file}" _include_file)
0467                 elseif(ARGS_DEFAULT_HEADER_CASE STREQUAL "UPPER_CASE")
0468                     string(TOUPPER "${_include_file}" _include_file)
0469                 endif()
0470                 # turn any namespaces into dir levels
0471                 string(REPLACE "::" "/" _include_file ${_include_file})
0472                 set(ECM_QTDESIGNERPLUGIN_${_widget}_INCLUDE_FILE "${_include_file}.${ARGS_DEFAULT_HEADER_EXTENSION}")
0473             endif()
0474             # icon
0475             set(_icon "${ECM_QTDESIGNERPLUGIN_${_widget}_ICON}")
0476             if(NOT _icon)
0477                 string(TOLOWER "${_class_name}" _icon)
0478                 # handle any namespaces
0479                 string(REPLACE "::" "_" _icon "${_icon}")
0480                 set(_icon "${ARGS_DEFAULT_ICON_DIR}/${_icon}.png")
0481                 if(EXISTS "${_icon}")
0482                     set(ECM_QTDESIGNERPLUGIN_${_widget}_ICON "${_icon}")
0483                 endif()
0484             endif()
0485         endforeach()
0486 
0487         set(_plugin_src_file "${_generation_dir}/designerplugin.cpp")
0488         set(_srcs
0489             ${ARGS_SOURCES}
0490             ${_plugin_src_file}
0491         )
0492 
0493         set(_icons)
0494         foreach(_widget ${ARGS_WIDGETS})
0495             list(APPEND _icons "${ECM_QTDESIGNERPLUGIN_${_widget}_ICON}")
0496         endforeach()
0497 
0498         # generate qrc file with icons
0499         if (_icons)
0500             set(_rc_file "${_generation_dir}/designerplugin.rc")
0501             set(_rc_work_file "${_rc_file}.work")
0502 
0503             _ecm_qtdesignerplugin_write_icon_qrc_file("${_rc_work_file}" "${_rc_icon_dir}" ${_icons})
0504             # avoid rebuilding if there was no change
0505             execute_process(
0506                 COMMAND ${CMAKE_COMMAND} -E copy_if_different "${_rc_work_file}" "${_rc_file}"
0507             )
0508             file(REMOVE "${_rc_work_file}")
0509 
0510             if (QT_MAJOR_VERSION EQUAL "5")
0511                 qt5_add_resources(_srcs ${_rc_file})
0512             else()
0513                 qt6_add_resources(_srcs ${_rc_file})
0514             endif()
0515         endif()
0516 
0517         # generate source file
0518         set(_collection_classname "${ARGS_NAME}QtDesignerWidgetCollection")
0519 
0520         set(_include_files
0521             # classes inherited
0522             QDesignerCustomWidgetCollectionInterface
0523             QDesignerCustomWidgetInterface
0524             QObject
0525             # classes used
0526             QIcon
0527             QString
0528             ${ARGS_INCLUDE_FILES}
0529         )
0530         foreach(_widget ${ARGS_WIDGETS})
0531             list(APPEND _include_files ${ECM_QTDESIGNERPLUGIN_${_widget}_INCLUDE_FILE})
0532         endforeach()
0533         list(REMOVE_DUPLICATES _include_files)
0534 
0535         set(_plugin_src_work_file "${_plugin_src_file}.work")
0536         file(WRITE ${_plugin_src_work_file} "// DO NOT EDIT! Generated from ecm_add_qtdesignerplugin()\n\n")
0537         foreach(_include_file ${_include_files})
0538             if (NOT ${_include_file} MATCHES "^[\"<]")
0539                 set(_include_file "<${_include_file}>")
0540             endif()
0541             file(APPEND ${_plugin_src_work_file} "#include ${_include_file}\n")
0542         endforeach()
0543         foreach(_widget ${ARGS_WIDGETS})
0544             _ecm_qtdesignerplugin_write_widget(${_plugin_src_work_file} ${_widget} ${ARGS_DEFAULT_GROUP} ${_rc_icon_dir})
0545         endforeach()
0546         file(APPEND ${_plugin_src_work_file} "
0547 class ${_collection_classname}
0548     : public QObject
0549     , public QDesignerCustomWidgetCollectionInterface
0550 {
0551     Q_OBJECT
0552     Q_INTERFACES(
0553         QDesignerCustomWidgetCollectionInterface
0554     )
0555 
0556     Q_PLUGIN_METADATA(IID \"org.qt-project.Qt.QDesignerCustomWidgetCollectionInterface\")
0557 
0558 public:
0559     explicit ${_collection_classname}(QObject* parent = nullptr);
0560 
0561 public: // QDesignerCustomWidgetCollectionInterface API
0562     QList<QDesignerCustomWidgetInterface*> customWidgets() const override;
0563 
0564 private:
0565     QList<QDesignerCustomWidgetInterface*> m_widgetFactories;
0566 };
0567 
0568 ${_collection_classname}::${_collection_classname}(QObject* parent)
0569     : QObject(parent)
0570 {
0571     m_widgetFactories = QList<QDesignerCustomWidgetInterface*>{
0572 "
0573         )
0574         foreach(_widget ${ARGS_WIDGETS})
0575             file(APPEND ${_plugin_src_work_file} "        new ${ECM_QTDESIGNERPLUGIN_${_widget}_FACTORY_CLASS_NAME}(this),\n")
0576         endforeach()
0577         file(APPEND ${_plugin_src_work_file}
0578 "    };
0579 }
0580 
0581 QList<QDesignerCustomWidgetInterface*> ${_collection_classname}::customWidgets() const
0582 {
0583     return m_widgetFactories;
0584 }
0585 
0586 #include \"designerplugin.moc\"
0587 "
0588         )
0589 
0590         # avoid rebuilding if there was no change
0591         execute_process(
0592             COMMAND ${CMAKE_COMMAND} -E copy_if_different "${_plugin_src_work_file}" "${_plugin_src_file}"
0593         )
0594         file(REMOVE "${_plugin_src_work_file}")
0595 
0596         # setup plugin binary
0597         add_library(${target} MODULE ${_srcs})
0598         if(NOT WIN32)
0599             # Since there are no libraries provided by this module,
0600             # there is no point including the build tree in RPath,
0601             # and then having to edit it at install time.
0602             set_target_properties(${target} PROPERTIES
0603                 SKIP_BUILD_RPATH TRUE
0604                 BUILD_WITH_INSTALL_RPATH TRUE
0605             )
0606         endif()
0607         if (ARGS_OUTPUT_NAME)
0608             set_target_properties(${target} PROPERTIES
0609                 OUTPUT_NAME ${ARGS_OUTPUT_NAME}
0610             )
0611         endif()
0612         target_link_libraries(${target} ${ARGS_LINK_LIBRARIES} Qt${QT_MAJOR_VERSION}::UiPlugin)
0613 
0614         if (DEFINED ARGS_COMPONENT)
0615             set(_component COMPONENT ${ARGS_COMPONENT})
0616         else()
0617             set(_component)
0618         endif()
0619 
0620         install(TARGETS ${target} DESTINATION ${ARGS_INSTALL_DESTINATION} ${_component})
0621     endif()
0622 endmacro()