diff --git a/editor/editor_help_search.cpp b/editor/editor_help_search.cpp index 7ece5097311..99459df96cc 100644 --- a/editor/editor_help_search.cpp +++ b/editor/editor_help_search.cpp @@ -476,7 +476,8 @@ bool EditorHelpSearch::Runner::_phase_match_classes() { // If the search term is empty, add any classes which are not script docs or which don't start with // a double-quotation. This will ensure that only C++ classes and explicitly named classes will // be added. - match.name = (term.is_empty() && (!class_doc->is_script_doc || class_doc->name[0] != '\"')) || _match_string(term, class_doc->name) || _match_keywords(term, class_doc->keywords); + match.name = (term.is_empty() && (!class_doc->is_script_doc || class_doc->name[0] != '\"')) || _match_string(term, class_doc->name); + match.keyword = _match_keywords(term, class_doc->keywords); } // Match members only if the term is long enough, to avoid slow performance from building a large tree. @@ -493,36 +494,56 @@ bool EditorHelpSearch::Runner::_phase_match_classes() { } if (search_flags & SEARCH_SIGNALS) { for (int i = 0; i < class_doc->signals.size(); i++) { - if (_all_terms_in_name(class_doc->signals[i].name) || _all_terms_in_keywords(class_doc->signals[i].keywords)) { - match.signals.push_back(const_cast(&class_doc->signals[i])); + MemberMatch signal; + signal.name = _all_terms_in_name(class_doc->signals[i].name); + signal.keyword = _match_keywords_in_all_terms(class_doc->signals[i].keywords); + if (signal.name || !signal.keyword.is_empty()) { + signal.doc = const_cast(&class_doc->signals[i]); + match.signals.push_back(signal); } } } if (search_flags & SEARCH_CONSTANTS) { for (int i = 0; i < class_doc->constants.size(); i++) { - if (_all_terms_in_name(class_doc->constants[i].name) || _all_terms_in_keywords(class_doc->constants[i].keywords)) { - match.constants.push_back(const_cast(&class_doc->constants[i])); + MemberMatch constant; + constant.name = _all_terms_in_name(class_doc->constants[i].name); + constant.keyword = _match_keywords_in_all_terms(class_doc->constants[i].keywords); + if (constant.name || !constant.keyword.is_empty()) { + constant.doc = const_cast(&class_doc->constants[i]); + match.constants.push_back(constant); } } } if (search_flags & SEARCH_PROPERTIES) { for (int i = 0; i < class_doc->properties.size(); i++) { - if (_all_terms_in_name(class_doc->properties[i].name) || _all_terms_in_keywords(class_doc->properties[i].keywords)) { - match.properties.push_back(const_cast(&class_doc->properties[i])); + MemberMatch property; + property.name = _all_terms_in_name(class_doc->properties[i].name); + property.keyword = _match_keywords_in_all_terms(class_doc->properties[i].keywords); + if (property.name || !property.keyword.is_empty()) { + property.doc = const_cast(&class_doc->properties[i]); + match.properties.push_back(property); } } } if (search_flags & SEARCH_THEME_ITEMS) { for (int i = 0; i < class_doc->theme_properties.size(); i++) { - if (_all_terms_in_name(class_doc->theme_properties[i].name) || _all_terms_in_keywords(class_doc->theme_properties[i].keywords)) { - match.theme_properties.push_back(const_cast(&class_doc->theme_properties[i])); + MemberMatch theme_property; + theme_property.name = _all_terms_in_name(class_doc->theme_properties[i].name); + theme_property.keyword = _match_keywords_in_all_terms(class_doc->theme_properties[i].keywords); + if (theme_property.name || !theme_property.keyword.is_empty()) { + theme_property.doc = const_cast(&class_doc->theme_properties[i]); + match.theme_properties.push_back(theme_property); } } } if (search_flags & SEARCH_ANNOTATIONS) { for (int i = 0; i < class_doc->annotations.size(); i++) { - if (_match_string(term, class_doc->annotations[i].name) || _all_terms_in_keywords(class_doc->annotations[i].keywords)) { - match.annotations.push_back(const_cast(&class_doc->annotations[i])); + MemberMatch annotation; + annotation.name = _all_terms_in_name(class_doc->annotations[i].name); + annotation.keyword = _match_keywords_in_all_terms(class_doc->annotations[i].keywords); + if (annotation.name || !annotation.keyword.is_empty()) { + annotation.doc = const_cast(&class_doc->annotations[i]); + match.annotations.push_back(annotation); } } } @@ -606,8 +627,8 @@ bool EditorHelpSearch::Runner::_phase_class_items() { _create_class_hierarchy(match); } } else { - if (match.name) { - _create_class_item(root_item, match.doc, false); + if (match.name || !match.keyword.is_empty()) { + _create_class_item(root_item, match.doc, false, match.name ? String() : match.keyword); } } @@ -636,14 +657,14 @@ bool EditorHelpSearch::Runner::_phase_member_items() { TreeItem *parent_item = (search_flags & SEARCH_SHOW_HIERARCHY) ? class_items[match.doc->name] : root_item; bool constructor_created = false; for (int i = 0; i < match.methods.size(); i++) { - String text = match.methods[i]->name; + String text = match.methods[i].doc->name; if (!constructor_created) { - if (match.doc->name == match.methods[i]->name) { + if (match.doc->name == match.methods[i].doc->name) { text += " " + TTR("(constructors)"); constructor_created = true; } } else { - if (match.doc->name == match.methods[i]->name) { + if (match.doc->name == match.methods[i].doc->name) { continue; } } @@ -662,8 +683,7 @@ bool EditorHelpSearch::Runner::_phase_member_items() { _create_theme_property_item(parent_item, match.doc, match.theme_properties[i]); } for (int i = 0; i < match.annotations.size(); i++) { - // Hide the redundant leading @ symbol. - _create_annotation_item(parent_item, match.doc, match.annotations[i]->name.substr(1), match.annotations[i]); + _create_annotation_item(parent_item, match.doc, match.annotations[i]); } ++iterator_match; @@ -677,16 +697,20 @@ bool EditorHelpSearch::Runner::_phase_select_match() { return true; } -void EditorHelpSearch::Runner::_match_method_name_and_push_back(Vector &p_methods, Vector *r_match_methods) { +void EditorHelpSearch::Runner::_match_method_name_and_push_back(Vector &p_methods, Vector> *r_match_methods) { // Constructors, Methods, Operators... for (int i = 0; i < p_methods.size(); i++) { String method_name = (search_flags & SEARCH_CASE_SENSITIVE) ? p_methods[i].name : p_methods[i].name.to_lower(); String keywords = (search_flags & SEARCH_CASE_SENSITIVE) ? p_methods[i].keywords : p_methods[i].keywords.to_lower(); - if (_all_terms_in_name(method_name) || _all_terms_in_keywords(keywords) || + MemberMatch method; + method.name = _all_terms_in_name(method_name); + method.keyword = _match_keywords_in_all_terms(keywords); + if (method.name || !method.keyword.is_empty() || (term.begins_with(".") && method_name.begins_with(term.substr(1))) || (term.ends_with("(") && method_name.ends_with(term.left(term.length() - 1).strip_edges())) || (term.begins_with(".") && term.ends_with("(") && method_name == term.substr(1, term.length() - 2).strip_edges())) { - r_match_methods->push_back(const_cast(&p_methods[i])); + method.doc = const_cast(&p_methods[i]); + r_match_methods->push_back(method); } } } @@ -700,13 +724,15 @@ bool EditorHelpSearch::Runner::_all_terms_in_name(const String &p_name) const { return true; } -bool EditorHelpSearch::Runner::_all_terms_in_keywords(const String &p_keywords) const { - for (const String &keyword : p_keywords.split(",")) { - if (_all_terms_in_name(keyword.strip_edges())) { - return true; +String EditorHelpSearch::Runner::_match_keywords_in_all_terms(const String &p_keywords) const { + String matching_keyword; + for (int i = 0; i < terms.size(); i++) { + matching_keyword = _match_keywords(terms[i], p_keywords); + if (matching_keyword.is_empty()) { + return String(); } } - return false; + return matching_keyword; } bool EditorHelpSearch::Runner::_match_string(const String &p_term, const String &p_string) const { @@ -717,13 +743,14 @@ bool EditorHelpSearch::Runner::_match_string(const String &p_term, const String } } -bool EditorHelpSearch::Runner::_match_keywords(const String &p_term, const String &p_keywords) const { - for (const String &keyword : p_keywords.split(",")) { - if (_match_string(p_term, keyword.strip_edges())) { - return true; +String EditorHelpSearch::Runner::_match_keywords(const String &p_term, const String &p_keywords) const { + for (const String &k : p_keywords.split(",")) { + const String keyword = k.strip_edges(); + if (_match_string(p_term, keyword)) { + return keyword; } } - return false; + return String(); } void EditorHelpSearch::Runner::_match_item(TreeItem *p_item, const String &p_text, bool p_is_keywords) { @@ -766,9 +793,26 @@ String EditorHelpSearch::Runner::_build_method_tooltip(const DocData::ClassDoc * } } tooltip += ")"; + tooltip += _build_keywords_tooltip(p_doc->keywords); return tooltip; } +String EditorHelpSearch::Runner::_build_keywords_tooltip(const String &p_keywords) const { + String tooltip; + if (p_keywords.is_empty()) { + return tooltip; + } + + tooltip = "\n\n" + TTR("Keywords") + ": "; + + for (const String &keyword : p_keywords.split(",")) { + tooltip += keyword.strip_edges().quote() + ", "; + } + + // Remove trailing comma and space. + return tooltip.left(-2); +} + TreeItem *EditorHelpSearch::Runner::_create_class_hierarchy(const ClassMatch &p_match) { if (p_match.doc->name.is_empty()) { return nullptr; @@ -790,7 +834,7 @@ TreeItem *EditorHelpSearch::Runner::_create_class_hierarchy(const ClassMatch &p_ } } - TreeItem *class_item = _create_class_item(parent_item, p_match.doc, !p_match.name); + TreeItem *class_item = _create_class_item(parent_item, p_match.doc, !p_match.name && p_match.keyword.is_empty(), p_match.name ? String() : p_match.keyword); class_items[p_match.doc->name] = class_item; return class_item; } @@ -815,15 +859,15 @@ bool EditorHelpSearch::Runner::_find_or_create_item(TreeItem *p_parent, const St } } -TreeItem *EditorHelpSearch::Runner::_create_class_item(TreeItem *p_parent, const DocData::ClassDoc *p_doc, bool p_gray) { +TreeItem *EditorHelpSearch::Runner::_create_class_item(TreeItem *p_parent, const DocData::ClassDoc *p_doc, bool p_gray, const String &p_matching_keyword) { String tooltip = DTR(p_doc->brief_description.strip_edges()); + tooltip += _build_keywords_tooltip(p_doc->keywords); const String item_meta = "class_name:" + p_doc->name; TreeItem *item = nullptr; if (_find_or_create_item(p_parent, item_meta, item)) { item->set_icon(0, EditorNode::get_singleton()->get_class_icon(p_doc->name)); - item->set_text(0, p_doc->name); item->set_text(1, TTR("Class")); item->set_tooltip_text(0, tooltip); item->set_tooltip_text(1, tooltip); @@ -845,6 +889,12 @@ TreeItem *EditorHelpSearch::Runner::_create_class_item(TreeItem *p_parent, const item->clear_custom_color(1); } + if (p_matching_keyword.is_empty()) { + item->set_text(0, p_doc->name); + } else { + item->set_text(0, p_doc->name + " - " + TTR(vformat("Matches the \"%s\" keyword.", p_matching_keyword))); + } + _match_item(item, p_doc->name); for (const String &keyword : p_doc->keywords.split(",")) { _match_item(item, keyword.strip_edges(), true); @@ -853,39 +903,44 @@ TreeItem *EditorHelpSearch::Runner::_create_class_item(TreeItem *p_parent, const return item; } -TreeItem *EditorHelpSearch::Runner::_create_method_item(TreeItem *p_parent, const DocData::ClassDoc *p_class_doc, const String &p_text, const DocData::MethodDoc *p_doc) { - String tooltip = _build_method_tooltip(p_class_doc, p_doc); - return _create_member_item(p_parent, p_class_doc->name, "MemberMethod", p_doc->name, p_text, TTRC("Method"), "method", tooltip, p_doc->keywords, p_doc->is_deprecated, p_doc->is_experimental); +TreeItem *EditorHelpSearch::Runner::_create_method_item(TreeItem *p_parent, const DocData::ClassDoc *p_class_doc, const String &p_text, const MemberMatch &p_match) { + String tooltip = _build_method_tooltip(p_class_doc, p_match.doc); + return _create_member_item(p_parent, p_class_doc->name, "MemberMethod", p_match.doc->name, p_text, TTRC("Method"), "method", tooltip, p_match.doc->keywords, p_match.doc->is_deprecated, p_match.doc->is_experimental, p_match.name ? String() : p_match.keyword); } -TreeItem *EditorHelpSearch::Runner::_create_signal_item(TreeItem *p_parent, const DocData::ClassDoc *p_class_doc, const DocData::MethodDoc *p_doc) { - String tooltip = _build_method_tooltip(p_class_doc, p_doc); - return _create_member_item(p_parent, p_class_doc->name, "MemberSignal", p_doc->name, p_doc->name, TTRC("Signal"), "signal", tooltip, p_doc->keywords, p_doc->is_deprecated, p_doc->is_experimental); +TreeItem *EditorHelpSearch::Runner::_create_signal_item(TreeItem *p_parent, const DocData::ClassDoc *p_class_doc, const MemberMatch &p_match) { + String tooltip = _build_method_tooltip(p_class_doc, p_match.doc); + return _create_member_item(p_parent, p_class_doc->name, "MemberSignal", p_match.doc->name, p_match.doc->name, TTRC("Signal"), "signal", tooltip, p_match.doc->keywords, p_match.doc->is_deprecated, p_match.doc->is_experimental, p_match.name ? String() : p_match.keyword); } -TreeItem *EditorHelpSearch::Runner::_create_annotation_item(TreeItem *p_parent, const DocData::ClassDoc *p_class_doc, const String &p_text, const DocData::MethodDoc *p_doc) { - String tooltip = _build_method_tooltip(p_class_doc, p_doc); - return _create_member_item(p_parent, p_class_doc->name, "MemberAnnotation", p_doc->name, p_text, TTRC("Annotation"), "annotation", tooltip, p_doc->keywords, p_doc->is_deprecated, p_doc->is_experimental); +TreeItem *EditorHelpSearch::Runner::_create_annotation_item(TreeItem *p_parent, const DocData::ClassDoc *p_class_doc, const MemberMatch &p_match) { + String tooltip = _build_method_tooltip(p_class_doc, p_match.doc); + // Hide the redundant leading @ symbol. + String text = p_match.doc->name.substr(1); + return _create_member_item(p_parent, p_class_doc->name, "MemberAnnotation", p_match.doc->name, text, TTRC("Annotation"), "annotation", tooltip, p_match.doc->keywords, p_match.doc->is_deprecated, p_match.doc->is_experimental, p_match.name ? String() : p_match.keyword); } -TreeItem *EditorHelpSearch::Runner::_create_constant_item(TreeItem *p_parent, const DocData::ClassDoc *p_class_doc, const DocData::ConstantDoc *p_doc) { - String tooltip = p_class_doc->name + "." + p_doc->name; - return _create_member_item(p_parent, p_class_doc->name, "MemberConstant", p_doc->name, p_doc->name, TTRC("Constant"), "constant", tooltip, p_doc->keywords, p_doc->is_deprecated, p_doc->is_experimental); +TreeItem *EditorHelpSearch::Runner::_create_constant_item(TreeItem *p_parent, const DocData::ClassDoc *p_class_doc, const MemberMatch &p_match) { + String tooltip = p_class_doc->name + "." + p_match.doc->name; + tooltip += _build_keywords_tooltip(p_match.doc->keywords); + return _create_member_item(p_parent, p_class_doc->name, "MemberConstant", p_match.doc->name, p_match.doc->name, TTRC("Constant"), "constant", tooltip, p_match.doc->keywords, p_match.doc->is_deprecated, p_match.doc->is_experimental, p_match.name ? String() : p_match.keyword); } -TreeItem *EditorHelpSearch::Runner::_create_property_item(TreeItem *p_parent, const DocData::ClassDoc *p_class_doc, const DocData::PropertyDoc *p_doc) { - String tooltip = p_doc->type + " " + p_class_doc->name + "." + p_doc->name; - tooltip += "\n " + p_class_doc->name + "." + p_doc->setter + "(value) setter"; - tooltip += "\n " + p_class_doc->name + "." + p_doc->getter + "() getter"; - return _create_member_item(p_parent, p_class_doc->name, "MemberProperty", p_doc->name, p_doc->name, TTRC("Property"), "property", tooltip, p_doc->keywords, p_doc->is_deprecated, p_doc->is_experimental); +TreeItem *EditorHelpSearch::Runner::_create_property_item(TreeItem *p_parent, const DocData::ClassDoc *p_class_doc, const MemberMatch &p_match) { + String tooltip = p_match.doc->type + " " + p_class_doc->name + "." + p_match.doc->name; + tooltip += "\n " + p_class_doc->name + "." + p_match.doc->setter + "(value) setter"; + tooltip += "\n " + p_class_doc->name + "." + p_match.doc->getter + "() getter"; + tooltip += _build_keywords_tooltip(p_match.doc->keywords); + return _create_member_item(p_parent, p_class_doc->name, "MemberProperty", p_match.doc->name, p_match.doc->name, TTRC("Property"), "property", tooltip, p_match.doc->keywords, p_match.doc->is_deprecated, p_match.doc->is_experimental, p_match.name ? String() : p_match.keyword); } -TreeItem *EditorHelpSearch::Runner::_create_theme_property_item(TreeItem *p_parent, const DocData::ClassDoc *p_class_doc, const DocData::ThemeItemDoc *p_doc) { - String tooltip = p_doc->type + " " + p_class_doc->name + "." + p_doc->name; - return _create_member_item(p_parent, p_class_doc->name, "MemberTheme", p_doc->name, p_doc->name, TTRC("Theme Property"), "theme_item", p_doc->keywords, tooltip, false, false); +TreeItem *EditorHelpSearch::Runner::_create_theme_property_item(TreeItem *p_parent, const DocData::ClassDoc *p_class_doc, const MemberMatch &p_match) { + String tooltip = p_match.doc->type + " " + p_class_doc->name + "." + p_match.doc->name; + tooltip += _build_keywords_tooltip(p_match.doc->keywords); + return _create_member_item(p_parent, p_class_doc->name, "MemberTheme", p_match.doc->name, p_match.doc->name, TTRC("Theme Property"), "theme_item", p_match.doc->keywords, tooltip, false, false, p_match.name ? String() : p_match.keyword); } -TreeItem *EditorHelpSearch::Runner::_create_member_item(TreeItem *p_parent, const String &p_class_name, const String &p_icon, const String &p_name, const String &p_text, const String &p_type, const String &p_metatype, const String &p_tooltip, const String &p_keywords, bool is_deprecated, bool is_experimental) { +TreeItem *EditorHelpSearch::Runner::_create_member_item(TreeItem *p_parent, const String &p_class_name, const String &p_icon, const String &p_name, const String &p_text, const String &p_type, const String &p_metatype, const String &p_tooltip, const String &p_keywords, bool p_is_deprecated, bool p_is_experimental, const String &p_matching_keyword) { const String item_meta = "class_" + p_metatype + ":" + p_class_name + ":" + p_name; TreeItem *item = nullptr; @@ -896,20 +951,25 @@ TreeItem *EditorHelpSearch::Runner::_create_member_item(TreeItem *p_parent, cons item->set_tooltip_text(1, p_tooltip); item->set_metadata(0, item_meta); - if (is_deprecated) { + if (p_is_deprecated) { Ref error_icon = ui_service->get_editor_theme_icon(SNAME("StatusError")); item->add_button(0, error_icon, 0, false, TTR("This member is marked as deprecated.")); - } else if (is_experimental) { + } else if (p_is_experimental) { Ref warning_icon = ui_service->get_editor_theme_icon(SNAME("NodeWarning")); item->add_button(0, warning_icon, 0, false, TTR("This member is marked as experimental.")); } } + String text; if (search_flags & SEARCH_SHOW_HIERARCHY) { - item->set_text(0, p_text); + text = p_text; } else { - item->set_text(0, p_class_name + "." + p_text); + text = p_class_name + "." + p_text; } + if (!p_matching_keyword.is_empty()) { + text += " - " + TTR(vformat("Matches the \"%s\" keyword.", p_matching_keyword)); + } + item->set_text(0, text); _match_item(item, p_name); for (const String &keyword : p_keywords.split(",")) { diff --git a/editor/editor_help_search.h b/editor/editor_help_search.h index 1982da04e84..003b98adf0a 100644 --- a/editor/editor_help_search.h +++ b/editor/editor_help_search.h @@ -117,20 +117,28 @@ class EditorHelpSearch::Runner : public RefCounted { }; int phase = 0; + template + struct MemberMatch { + T *doc = nullptr; + bool name = false; + String keyword; + }; + struct ClassMatch { DocData::ClassDoc *doc = nullptr; bool name = false; - Vector constructors; - Vector methods; - Vector operators; - Vector signals; - Vector constants; - Vector properties; - Vector theme_properties; - Vector annotations; + String keyword; + Vector> constructors; + Vector> methods; + Vector> operators; + Vector> signals; + Vector> constants; + Vector> properties; + Vector> theme_properties; + Vector> annotations; bool required() { - return name || methods.size() || signals.size() || constants.size() || properties.size() || theme_properties.size() || annotations.size(); + return name || !keyword.is_empty() || methods.size() || signals.size() || constants.size() || properties.size() || theme_properties.size() || annotations.size(); } }; @@ -167,22 +175,23 @@ class EditorHelpSearch::Runner : public RefCounted { bool _phase_select_match(); String _build_method_tooltip(const DocData::ClassDoc *p_class_doc, const DocData::MethodDoc *p_doc) const; + String _build_keywords_tooltip(const String &p_keywords) const; - void _match_method_name_and_push_back(Vector &p_methods, Vector *r_match_methods); + void _match_method_name_and_push_back(Vector &p_methods, Vector> *r_match_methods); bool _all_terms_in_name(const String &p_name) const; - bool _all_terms_in_keywords(const String &p_name) const; + String _match_keywords_in_all_terms(const String &p_keywords) const; bool _match_string(const String &p_term, const String &p_string) const; - bool _match_keywords(const String &p_term, const String &p_keywords) const; + String _match_keywords(const String &p_term, const String &p_keywords) const; void _match_item(TreeItem *p_item, const String &p_text, bool p_is_keywords = false); TreeItem *_create_class_hierarchy(const ClassMatch &p_match); - TreeItem *_create_class_item(TreeItem *p_parent, const DocData::ClassDoc *p_doc, bool p_gray); - TreeItem *_create_method_item(TreeItem *p_parent, const DocData::ClassDoc *p_class_doc, const String &p_text, const DocData::MethodDoc *p_doc); - TreeItem *_create_signal_item(TreeItem *p_parent, const DocData::ClassDoc *p_class_doc, const DocData::MethodDoc *p_doc); - TreeItem *_create_annotation_item(TreeItem *p_parent, const DocData::ClassDoc *p_class_doc, const String &p_text, const DocData::MethodDoc *p_doc); - TreeItem *_create_constant_item(TreeItem *p_parent, const DocData::ClassDoc *p_class_doc, const DocData::ConstantDoc *p_doc); - TreeItem *_create_property_item(TreeItem *p_parent, const DocData::ClassDoc *p_class_doc, const DocData::PropertyDoc *p_doc); - TreeItem *_create_theme_property_item(TreeItem *p_parent, const DocData::ClassDoc *p_class_doc, const DocData::ThemeItemDoc *p_doc); - TreeItem *_create_member_item(TreeItem *p_parent, const String &p_class_name, const String &p_icon, const String &p_name, const String &p_text, const String &p_type, const String &p_metatype, const String &p_tooltip, const String &p_keywords, bool is_deprecated, bool is_experimental); + TreeItem *_create_class_item(TreeItem *p_parent, const DocData::ClassDoc *p_doc, bool p_gray, const String &p_matching_keyword); + TreeItem *_create_method_item(TreeItem *p_parent, const DocData::ClassDoc *p_class_doc, const String &p_text, const MemberMatch &p_match); + TreeItem *_create_signal_item(TreeItem *p_parent, const DocData::ClassDoc *p_class_doc, const MemberMatch &p_match); + TreeItem *_create_annotation_item(TreeItem *p_parent, const DocData::ClassDoc *p_class_doc, const MemberMatch &p_match); + TreeItem *_create_constant_item(TreeItem *p_parent, const DocData::ClassDoc *p_class_doc, const MemberMatch &p_match); + TreeItem *_create_property_item(TreeItem *p_parent, const DocData::ClassDoc *p_class_doc, const MemberMatch &p_match); + TreeItem *_create_theme_property_item(TreeItem *p_parent, const DocData::ClassDoc *p_class_doc, const MemberMatch &p_match); + TreeItem *_create_member_item(TreeItem *p_parent, const String &p_class_name, const String &p_icon, const String &p_name, const String &p_text, const String &p_type, const String &p_metatype, const String &p_tooltip, const String &p_keywords, bool p_is_deprecated, bool p_is_experimental, const String &p_matching_keyword); public: bool work(uint64_t slot = 100000);