From bc636f90fcc3dab4292a2e1fb2bcc7ebd9ec4d2e Mon Sep 17 00:00:00 2001 From: =?utf8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 13 Sep 2018 18:47:34 +0200 Subject: [PATCH] doxygen: support Qt signals and slots. --- doc/doxygen.rst | 22 ++- doxygen/dox2html5.py | 41 ++++- doxygen/templates/base-class-reference.html | 74 +++++++- doxygen/templates/details-func.html | 2 +- doxygen/templates/entry-func.html | 2 +- doxygen/test/cpp_signals_slots/Doxyfile | 15 ++ doxygen/test/cpp_signals_slots/File.h | 88 ++++++++++ .../test/cpp_signals_slots/classClass.html | 162 ++++++++++++++++++ doxygen/test/test_cpp.py | 8 + 9 files changed, 403 insertions(+), 11 deletions(-) create mode 100644 doxygen/test/cpp_signals_slots/Doxyfile create mode 100644 doxygen/test/cpp_signals_slots/File.h create mode 100644 doxygen/test/cpp_signals_slots/classClass.html diff --git a/doc/doxygen.rst b/doc/doxygen.rst index da428dcf..c0c3db5e 100644 --- a/doc/doxygen.rst +++ b/doc/doxygen.rst @@ -1248,6 +1248,12 @@ Property Description :py:`compound.public_funcs` List of public functions. Set only for classes. See `Function properties`_ for details. +:py:`compound.signals` List of Qt signals. Set only for + classes. See `Function properties`_ for + details. +:py:`compound.public_slots` List of public Qt slots. Set only for + classes. See `Function properties`_ for + details. :py:`compound.public_static_vars` List of public static variables. Set only for classes. See `Variable properties`_ for details. @@ -1263,6 +1269,9 @@ Property Description :py:`compound.protected_funcs` List of protected functions. Set only for classes. See `Function properties`_ for details. +:py:`compound.protected_slots` List of protected Qt slots. Set only + for classes. See `Function properties`_ + for details. :py:`compound.protected_static_vars` List of protected static variables. Set only for classes. See `Variable properties`_ for details. @@ -1272,6 +1281,9 @@ Property Description :py:`compound.private_funcs` List of documented private virtual functions. Set only for classes. See `Function properties`_ for details. +:py:`compound.private_slots` List of documented private virtual Qt + slots. Set only for classes. See + `Function properties`_ for details. :py:`compound.friend_funcs` List of documented friend functions. Set only for classes. See `Function properties`_ for details. @@ -1499,8 +1511,10 @@ Property Description `````````````````````` The :py:`commpound.funcs`, :py:`compound.public_static_funcs`, -:py:`compound.public_funcs`, :py:`compound.protected_static_funcs`, -:py:`compound.protected_funcs`, :py:`compound.private_funcs`, +:py:`compound.public_funcs`, :py:`compound.signals`, +:py:`compound.public_slots`, :py:`compound.protected_static_funcs`, +:py:`compound.protected_funcs`, :py:`compound.protected_slots`, +:py:`compound.private_funcs`, :py:`compound.private_slots`, :py:`compound.friend_funcs` and :py:`compound.related_funcs` properties contain a list of functions, where every item has the following properties: @@ -1555,6 +1569,10 @@ Property Description :py:`func.is_constexpr` If the function is :cpp:`constexpr` :py:`func.is_defaulted` If the function is :cpp:`default`\ ed :py:`func.is_deleted` If the function is :cpp:`delete`\ d +:py:`func.is_signal` If the function is a Qt signal. Set only for + member functions. +:py:`func.is_slot` If the function is a Qt slot. Set only for + member functions. =============================== =============================================== The :py:`func.params` is a list of function parameters and their description. diff --git a/doxygen/dox2html5.py b/doxygen/dox2html5.py index 0fac50f1..056648ab 100755 --- a/doxygen/dox2html5.py +++ b/doxygen/dox2html5.py @@ -1570,7 +1570,7 @@ def parse_typedef(state: State, element: ET.Element): return None def parse_func(state: State, element: ET.Element): - assert element.tag == 'memberdef' and element.attrib['kind'] in ['function', 'friend'] + assert element.tag == 'memberdef' and element.attrib['kind'] in ['function', 'friend', 'signal', 'slot'] func = Empty() state.current_definition_url_base, func.base_url, func.id = parse_id(element) @@ -1627,6 +1627,8 @@ def parse_func(state: State, element: ET.Element): if element.attrib['kind'] != 'friend': func.is_protected = element.attrib['prot'] == 'protected' func.is_private = element.attrib['prot'] == 'private' + func.is_signal = element.attrib['kind'] == 'signal' + func.is_slot = element.attrib['kind'] == 'slot' func.has_template_details, func.templates = parse_template_params(state, element.find('templateparamlist'), templates) @@ -2082,14 +2084,18 @@ def parse_xml(state: State, xml: str): compound.public_static_funcs = [] compound.typeless_funcs = [] compound.public_funcs = [] + compound.signals = [] + compound.public_slots = [] compound.public_static_vars = [] compound.public_vars = [] compound.protected_types = [] compound.protected_static_funcs = [] compound.protected_funcs = [] + compound.protected_slots = [] compound.protected_static_vars = [] compound.protected_vars = [] compound.private_funcs = [] + compound.private_slots = [] compound.related = [] compound.friend_funcs = [] compound.groups = [] @@ -2341,6 +2347,20 @@ def parse_xml(state: State, xml: str): compound.typeless_funcs += [func] if func.has_details: compound.has_func_details = True + elif compounddef_child.attrib['kind'] == 'signal': + for memberdef in compounddef_child: + func = parse_func(state, memberdef) + if func: + compound.signals += [func] + if func.has_details: compound.has_func_details = True + + elif compounddef_child.attrib['kind'] == 'public-slot': + for memberdef in compounddef_child: + func = parse_func(state, memberdef) + if func: + compound.public_slots += [func] + if func.has_details: compound.has_func_details = True + elif compounddef_child.attrib['kind'] == 'public-static-attrib': for memberdef in compounddef_child: var = parse_var(state, memberdef) @@ -2384,6 +2404,13 @@ def parse_xml(state: State, xml: str): compound.typeless_funcs += [func] if func.has_details: compound.has_func_details = True + elif compounddef_child.attrib['kind'] == 'protected-slot': + for memberdef in compounddef_child: + func = parse_func(state, memberdef) + if func: + compound.protected_slots += [func] + if func.has_details: compound.has_func_details = True + elif compounddef_child.attrib['kind'] == 'protected-static-attrib': for memberdef in compounddef_child: var = parse_var(state, memberdef) @@ -2398,17 +2425,19 @@ def parse_xml(state: State, xml: str): compound.protected_vars += [var] if var.has_details: compound.has_var_details = True - elif compounddef_child.attrib['kind'] == 'private-func': + elif compounddef_child.attrib['kind'] in ['private-func', 'private-slot']: # Gather only private functions that are virtual and # documented for memberdef in compounddef_child: if memberdef.attrib['virt'] == 'non-virtual' or (not memberdef.find('briefdescription').text and not memberdef.find('detaileddescription').text): - assert True # only because coverage.py can't handle continue :/ - continue # pragma: no cover + continue func = parse_func(state, memberdef) if func: - compound.private_funcs += [func] + if compounddef_child.attrib['kind'] == 'private-slot': + compound.private_slots += [func] + else: + compound.private_funcs += [func] if func.has_details: compound.has_func_details = True elif compounddef_child.attrib['kind'] == 'related': @@ -2472,7 +2501,7 @@ def parse_xml(state: State, xml: str): if typedef: list += [('typedef', typedef)] if typedef.has_details: compound.has_typedef_details = True - elif memberdef.attrib['kind'] == 'function': + elif memberdef.attrib['kind'] in ['function', 'signal', 'slot']: # Gather only private functions that are virtual and # documented if memberdef.attrib['prot'] == 'private' and (memberdef.attrib['virt'] == 'non-virtual' or (not memberdef.find('briefdescription').text and not memberdef.find('detaileddescription').text)): diff --git a/doxygen/templates/base-class-reference.html b/doxygen/templates/base-class-reference.html index f80af0cb..71cf5424 100644 --- a/doxygen/templates/base-class-reference.html +++ b/doxygen/templates/base-class-reference.html @@ -41,7 +41,7 @@ {% endif %} - {% if compound.sections or compound.public_types or compound.public_static_funcs or compound.typeless_funcs or compound.public_funcs or compound.public_static_vars or compound.public_vars or compound.protected_types or compound.protected_static_funcs or compound.protected_funcs or compound.protected_static_vars or compound.protected_vars or compound.private_funcs or compound.groups or compound.friend_funcs or compound.related %} + {% if compound.sections or compound.public_types or compound.public_static_funcs or compound.typeless_funcs or compound.public_funcs or compound.signals or compound.public_slots or compound.public_static_vars or compound.public_vars or compound.protected_types or compound.protected_static_funcs or compound.protected_funcs or compound.protected_signals or compound.protected_static_vars or compound.protected_vars or compound.private_funcs or compound.private_slots or compound.groups or compound.friend_funcs or compound.related %}

Contents

{% endif %} {% set j = joiner(',\n ') %} - {{ func.prefix }}{{ func.type }} {{ prefix }}{{ func.name }}({% for param in func.params %}{{ j() }}{{ param.type_name }}{% if param.default %} = {{ param.default }}{% endif %}{% endfor %}){{ func.suffix }}{% if func.is_explicit %} explicit {% endif %}{% if func.is_pure_virtual %} pure virtual{% elif func.is_virtual %} virtual{% endif %}{% if func.is_protected %} protected{% elif func.is_private %} private{% endif %}{% if func.is_defaulted %} defaulted{% endif %}{% if func.is_deleted %} deleted{% endif %}{% if func.is_constexpr %} constexpr{% endif %}{% if func.is_noexcept %} noexcept{% endif %} + {{ func.prefix }}{{ func.type }} {{ prefix }}{{ func.name }}({% for param in func.params %}{{ j() }}{{ param.type_name }}{% if param.default %} = {{ param.default }}{% endif %}{% endfor %}){{ func.suffix }}{% if func.is_explicit %} explicit {% endif %}{% if func.is_pure_virtual %} pure virtual{% elif func.is_virtual %} virtual{% endif %}{% if func.is_protected %} protected{% if func.is_slot %} slot{% endif %}{% elif func.is_private %} private{% if func.is_slot %} slot{% endif %}{% elif func.is_signal %} signal{% elif func.is_slot %} public slot{% endif %}{% if func.is_defaulted %} defaulted{% endif %}{% if func.is_deleted %} deleted{% endif %}{% if func.is_constexpr %} constexpr{% endif %}{% if func.is_noexcept %} noexcept{% endif %} {% if func.brief %}

{{ func.brief }}

diff --git a/doxygen/templates/entry-func.html b/doxygen/templates/entry-func.html index d2060aca..66e03b7f 100644 --- a/doxygen/templates/entry-func.html +++ b/doxygen/templates/entry-func.html @@ -4,6 +4,6 @@
template<{% for t in func.templates %}{{ j() }}{{ t.type }}{% if t.name %} {{ t.name }}{% endif %}{% if t.default %} = {{ t.default }}{% endif %}{% endfor %}>
{% endif %} {% set j = joiner(',\n ') %} - {{ func.prefix }}{% if func.type == 'void' %}void {% elif func.type %}auto {% endif %}{{ func.name }}({% for param in func.params %}{{ j() }}{{ param.type_name }}{% if param.default %} = {{ param.default }}{% endif %}{% endfor %}){{ func.suffix }}{% if func.type and func.type != 'void' %} -> {{ func.type }}{% endif %}{% if func.is_deprecated %} deprecated{% endif %}{% if not func.type or mark_nonpublic %}{% if func.is_protected %} protected{% elif func.is_private %} private{% endif %}{% endif %}{% if func.is_defaulted %} defaulted{% endif %}{% if func.is_deleted %} deleted{% endif %}{% if func.is_explicit %} explicit {% endif %}{% if func.is_pure_virtual %} pure virtual{% elif func.is_virtual %} virtual{% endif %}{% if func.is_constexpr %} constexpr{% endif %}{% if func.is_noexcept %} noexcept{% endif %} + {{ func.prefix }}{% if func.type == 'void' %}void {% elif func.type %}auto {% endif %}{{ func.name }}({% for param in func.params %}{{ j() }}{{ param.type_name }}{% if param.default %} = {{ param.default }}{% endif %}{% endfor %}){{ func.suffix }}{% if func.type and func.type != 'void' %} -> {{ func.type }}{% endif %}{% if func.is_deprecated %} deprecated{% endif %}{% if not func.type or mark_nonpublic %}{% if func.is_protected %} protected{% if func.is_slot %} slot{% endif %}{% elif func.is_private %} private{% if func.is_slot %} slot{% endif %}{% elif func.is_signal %} signal{% elif func.is_slot %} public slot{% endif %}{% endif %}{% if func.is_defaulted %} defaulted{% endif %}{% if func.is_deleted %} deleted{% endif %}{% if func.is_explicit %} explicit {% endif %}{% if func.is_pure_virtual %} pure virtual{% elif func.is_virtual %} virtual{% endif %}{% if func.is_constexpr %} constexpr{% endif %}{% if func.is_noexcept %} noexcept{% endif %}
{{ func.brief }}
diff --git a/doxygen/test/cpp_signals_slots/Doxyfile b/doxygen/test/cpp_signals_slots/Doxyfile new file mode 100644 index 00000000..0451f2aa --- /dev/null +++ b/doxygen/test/cpp_signals_slots/Doxyfile @@ -0,0 +1,15 @@ +INPUT = File.h +AUTOLINK_SUPPORT = NO +QUIET = YES +GENERATE_HTML = NO +GENERATE_LATEX = NO +GENERATE_XML = YES +XML_PROGRAMLISTING = NO + +##! M_PAGE_FINE_PRINT = +##! M_THEME_COLOR = +##! M_FAVICON = +##! M_LINKS_NAVBAR1 = +##! M_LINKS_NAVBAR2 = +##! M_SEARCH_DISABLED = YES + diff --git a/doxygen/test/cpp_signals_slots/File.h b/doxygen/test/cpp_signals_slots/File.h new file mode 100644 index 00000000..c8d7b37a --- /dev/null +++ b/doxygen/test/cpp_signals_slots/File.h @@ -0,0 +1,88 @@ +/** @file + * @brief Uh + */ + +/** @brief A class */ +class Class { + signals: + /** + * @brief A signal + * + * Details. + */ + void signal(); + + public slots: + /** + * @brief A public slot + * + * Details. + */ + void publicSlot(); + + protected slots: + /** + * @brief A protected slot + * + * Details. + */ + void protectedSlot(); + + private slots: + /** + * @brief A private virtual slot + * + * Shown because it's virtual. + */ + virtual void privateVirtualSlot(); + + /** + * @brief A private slot + * + * Non-virtual, so hidden. + */ + void privateSlot(); + + /** @{ @name A user-defined group */ + + signals: + /** + * @brief A grouped signal + * + * Details. + */ + void groupedSignal(); + + public slots: + /** + * @brief A public grouped slot + * + * Details. + */ + void publicGroupedSlot(); + + protected slots: + /** + * @brief A protected grouped slot + * + * Details. + */ + void protectedGroupedSlot(); + + private slots: + /** + * @brief A private virtual grouped slot + * + * Shown because it's virtual. + */ + virtual void privateVirtualGroupedSlot(); + + /** + * @brief A private grouped slot + * + * Non-virtual, so hidden. + */ + void privateGroupedSlot(); + + /*@}*/ +}; diff --git a/doxygen/test/cpp_signals_slots/classClass.html b/doxygen/test/cpp_signals_slots/classClass.html new file mode 100644 index 00000000..08cb0eeb --- /dev/null +++ b/doxygen/test/cpp_signals_slots/classClass.html @@ -0,0 +1,162 @@ + + + + + Class class | My Project + + + + + +
+
+
+
+
+

+ Class class +

+

A class.

+
+

Contents

+ +
+
+

Signals

+
+
+ void signal() +
+
A signal.
+
+
+
+

Public slots

+
+
+ void publicSlot() +
+
A public slot.
+
+
+
+

Protected slots

+
+
+ void protectedSlot() +
+
A protected slot.
+
+
+
+

Private slots

+
+
+ void privateVirtualSlot() virtual +
+
A private virtual slot.
+
+
+
+

A user-defined group

+
+
+ void groupedSignal() signal +
+
A grouped signal.
+
+ void publicGroupedSlot() public slot +
+
A public grouped slot.
+
+ void protectedGroupedSlot() protected slot +
+
A protected grouped slot.
+
+ void privateVirtualGroupedSlot() private slot virtual +
+
A private virtual grouped slot.
+
+
+
+

Function documentation

+
+

+ void Class::signal() signal +

+

A signal.

+

Details.

+
+
+

+ void Class::publicSlot() public slot +

+

A public slot.

+

Details.

+
+
+

+ void Class::protectedSlot() protected slot +

+

A protected slot.

+

Details.

+
+
+

+ void Class::privateVirtualSlot() virtual private slot +

+

A private virtual slot.

+

Shown because it's virtual.

+
+
+

+ void Class::groupedSignal() signal +

+

A grouped signal.

+

Details.

+
+
+

+ void Class::publicGroupedSlot() public slot +

+

A public grouped slot.

+

Details.

+
+
+

+ void Class::protectedGroupedSlot() protected slot +

+

A protected grouped slot.

+

Details.

+
+
+

+ void Class::privateVirtualGroupedSlot() virtual private slot +

+

A private virtual grouped slot.

+

Shown because it's virtual.

+
+
+
+
+
+
+ + diff --git a/doxygen/test/test_cpp.py b/doxygen/test/test_cpp.py index 44aca62d..5bab4020 100644 --- a/doxygen/test/test_cpp.py +++ b/doxygen/test/test_cpp.py @@ -72,3 +72,11 @@ class Friends(IntegrationTestCase): self.run_dox2html5(wildcard='class*.xml') self.assertEqual(*self.actual_expected_contents('classClass.html')) self.assertEqual(*self.actual_expected_contents('classTemplate.html')) + +class SignalsSlots(IntegrationTestCase): + def __init__(self, *args, **kwargs): + super().__init__(__file__, 'signals_slots', *args, **kwargs) + + def test(self): + self.run_dox2html5(wildcard='classClass.xml') + self.assertEqual(*self.actual_expected_contents('classClass.html')) -- 2.30.2