Lua: Fix properties

Previously the `HAS_MEM_FUNC` would only work if func
was a direct member of `T` but not if it was a member
of a Base of `T`.
Using C++20 concepts the checks get much easier and
now work for members of a base class too.

Change-Id: I4e35069f4609cd65365d3c4e5883ae3b27204131
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
Marcus Tillmanns
2024-10-28 09:47:15 +01:00
parent 3d12376a03
commit 42113e28e6

View File

@@ -77,131 +77,123 @@ void constructWidget(std::unique_ptr<T> &widget, const sol::table &children)
} }
} }
#define HAS_MEM_FUNC(func, name) \ // clang-format off
template<typename T, typename Sign> \ #define CREATE_HAS_FUNC(name, ...) \
struct name \ template<class T> concept has_##name = requires { \
{ \ { std::declval<T>().name(__VA_ARGS__) } -> std::same_as<void>; \
typedef char yes[1]; \ };
typedef char no[2]; \ // clang-format on
template<typename U, U> \
struct type_check; \
template<typename _1> \
static yes &chk(type_check<Sign, &_1::func> *); \
template<typename> \
static no &chk(...); \
static bool const value = sizeof(chk<T>(0)) == sizeof(yes); \
}
HAS_MEM_FUNC(onTextChanged, hasOnTextChanged); CREATE_HAS_FUNC(onTextChanged, nullptr, nullptr)
HAS_MEM_FUNC(onClicked, hasOnClicked); CREATE_HAS_FUNC(onClicked, nullptr, nullptr)
HAS_MEM_FUNC(setText, hasSetText); CREATE_HAS_FUNC(setText, QString())
HAS_MEM_FUNC(setMarkdown, hasSetMarkdown); CREATE_HAS_FUNC(setMarkdown, QString())
HAS_MEM_FUNC(setReadOnly, hasSetReadOnly); CREATE_HAS_FUNC(setReadOnly, bool())
HAS_MEM_FUNC(setTitle, hasSetTitle); CREATE_HAS_FUNC(setTitle, QString())
HAS_MEM_FUNC(setValue, hasSetValue); CREATE_HAS_FUNC(setValue, int())
HAS_MEM_FUNC(setSize, hasSetSize); CREATE_HAS_FUNC(setSize, int(), int())
HAS_MEM_FUNC(setWindowFlags, hasSetWindowFlags); CREATE_HAS_FUNC(setWindowFlags, Qt::WindowFlags())
HAS_MEM_FUNC(setWidgetAttribute, hasSetWidgetAttribute); CREATE_HAS_FUNC(setWidgetAttribute, Qt::WidgetAttribute(), bool())
HAS_MEM_FUNC(setAutoFillBackground, hasSetAutoFillBackground); CREATE_HAS_FUNC(setAutoFillBackground, bool())
HAS_MEM_FUNC(setIconPath, hasSetIconPath); CREATE_HAS_FUNC(setIconPath, Utils::FilePath())
HAS_MEM_FUNC(setFlat, hasSetFlat); CREATE_HAS_FUNC(setFlat, bool())
HAS_MEM_FUNC(setOpenExternalLinks, hasSetOpenExternalLinks); CREATE_HAS_FUNC(setOpenExternalLinks, bool())
HAS_MEM_FUNC(setIconSize, hasSetIconSize); CREATE_HAS_FUNC(setIconSize, QSize())
HAS_MEM_FUNC(setWordWrap, hasSetWordWrap); CREATE_HAS_FUNC(setWordWrap, bool())
HAS_MEM_FUNC(setTextFormat, hasSetTextFormat); CREATE_HAS_FUNC(setTextFormat, Qt::TextFormat())
HAS_MEM_FUNC(setRightSideIconPath, hasSetRightSideIconPath); CREATE_HAS_FUNC(setRightSideIconPath, Utils::FilePath())
HAS_MEM_FUNC(setPlaceHolderText, hasSetPlaceHolderText); CREATE_HAS_FUNC(setPlaceHolderText, QString())
HAS_MEM_FUNC(setCompleter, hasSetCompleter); CREATE_HAS_FUNC(setCompleter, nullptr)
HAS_MEM_FUNC(setMinimumHeight, hasSetMinimumHeight); CREATE_HAS_FUNC(setMinimumHeight, int())
HAS_MEM_FUNC(onReturnPressed, hasOnReturnPressed); CREATE_HAS_FUNC(onReturnPressed, nullptr, nullptr)
HAS_MEM_FUNC(onRightSideIconClicked, hasOnRightSideIconClicked); CREATE_HAS_FUNC(onRightSideIconClicked, nullptr, nullptr)
HAS_MEM_FUNC(setTextInteractionFlags, hasSetTextInteractionFlags); CREATE_HAS_FUNC(setTextInteractionFlags, Qt::TextInteractionFlags())
HAS_MEM_FUNC(setFixedSize, hasSetFixedSize); CREATE_HAS_FUNC(setFixedSize, QSize())
template<class T> template<class T>
void setProperties(std::unique_ptr<T> &item, const sol::table &children, QObject *guard) { void setProperties(std::unique_ptr<T> &item, const sol::table &children, QObject *guard)
if constexpr (hasSetTextInteractionFlags<T, void (T::*)(Qt::TextInteractionFlags)>::value) { {
if constexpr (has_setTextInteractionFlags<T>) {
const auto interactionFlags = children.get<sol::optional<sol::table>>("interactionFlags"); const auto interactionFlags = children.get<sol::optional<sol::table>>("interactionFlags");
if (interactionFlags) { if (interactionFlags) {
item->setTextInteractionFlags(tableToFlags<Qt::TextInteractionFlag>(*interactionFlags)); item->setTextInteractionFlags(tableToFlags<Qt::TextInteractionFlag>(*interactionFlags));
} }
} }
if constexpr (hasSetFixedSize<T, void (T::*)(int, int)>::value) { if constexpr (has_setFixedSize<T>) {
sol::optional<QSize> size = children.get<sol::optional<QSize>>("fixedSize"); sol::optional<QSize> size = children.get<sol::optional<QSize>>("fixedSize");
if (size) if (size)
item->setFixedSize(size->width(), size->height()); item->setFixedSize(size->width(), size->height());
} }
if constexpr (hasSetWordWrap<T, void (T::*)(bool)>::value) { if constexpr (has_setWordWrap<T>) {
const auto wrap = children.get<sol::optional<bool>>("wordWrap"); const auto wrap = children.get<sol::optional<bool>>("wordWrap");
if (wrap) if (wrap)
item->setWordWrap(*wrap); item->setWordWrap(*wrap);
} }
if constexpr (hasSetTextFormat<T, void (T::*)(Qt::TextFormat)>::value) { if constexpr (has_setTextFormat<T>) {
const auto format = children.get<sol::optional<Qt::TextFormat>>("textFormat"); const auto format = children.get<sol::optional<Qt::TextFormat>>("textFormat");
if (format) if (format)
item->setTextFormat(*format); item->setTextFormat(*format);
} }
if constexpr (hasSetRightSideIconPath<T, void (T::*)(const Utils::FilePath &)>::value) { if constexpr (has_setRightSideIconPath<T>) {
const auto path = children.get<sol::optional<Utils::FilePath>>("rightSideIconPath"); const auto path = children.get<sol::optional<Utils::FilePath>>("rightSideIconPath");
if (path) if (path)
item->setRightSideIconPath(*path); item->setRightSideIconPath(*path);
} }
if constexpr (hasSetPlaceHolderText<T, void (T::*)(const QString &)>::value) { if constexpr (has_setPlaceHolderText<T>) {
const auto text = children.get<sol::optional<QString>>("placeHolderText"); const auto text = children.get<sol::optional<QString>>("placeHolderText");
if (text) if (text)
item->setPlaceHolderText(*text); item->setPlaceHolderText(*text);
} }
if constexpr (hasSetCompleter<T, void (T::*)(QCompleter *)>::value) { if constexpr (has_setCompleter<T>) {
const auto completer = children.get<QCompleter *>("completer"); const auto completer = children.get<QCompleter *>("completer");
if (completer) if (completer)
item->setCompleter(completer); item->setCompleter(completer);
} }
if constexpr (hasSetMinimumHeight<T, void (T::*)(int)>::value) { if constexpr (has_setMinimumHeight<T>) {
const auto minHeight = children.get<sol::optional<int>>("minimumHeight"); const auto minHeight = children.get<sol::optional<int>>("minimumHeight");
if (minHeight) if (minHeight)
item->setMinimumHeight(*minHeight); item->setMinimumHeight(*minHeight);
} }
if constexpr (hasOnReturnPressed<T, void (T::*)(const std::function<void()> &, QObject *)>::value) { if constexpr (has_onReturnPressed<T>) {
const auto callback = children.get<sol::optional<sol::function>>("onReturnPressed"); const auto callback = children.get<sol::optional<sol::function>>("onReturnPressed");
if (callback) if (callback) {
{
item->onReturnPressed([func = *callback]() { void_safe_call(func); }, guard); item->onReturnPressed([func = *callback]() { void_safe_call(func); }, guard);
} }
} }
if constexpr (hasOnRightSideIconClicked<T, void (T::*)(const std::function<void()> &)>::value) { if constexpr (has_onRightSideIconClicked<T>) {
const auto callback = children.get<sol::optional<sol::function>>("onRightSideIconClicked"); const auto callback = children.get<sol::optional<sol::function>>("onRightSideIconClicked");
if (callback) if (callback)
item->onRightSideIconClicked([func = *callback]() { void_safe_call(func); }, guard); item->onRightSideIconClicked([func = *callback]() { void_safe_call(func); }, guard);
} }
if constexpr (hasSetFlat<T, void (T::*)(bool)>::value) { if constexpr (has_setFlat<T>) {
const auto flat = children.get<sol::optional<bool>>("flat"); const auto flat = children.get<sol::optional<bool>>("flat");
if (flat) if (flat)
item->setFlat(*flat); item->setFlat(*flat);
} }
if constexpr (hasSetIconPath<T, void (T::*)(const FilePath &)>::value) { if constexpr (has_setIconPath<T>) {
const auto iconPath = children.get<sol::optional<FilePath>>("iconPath"); const auto iconPath = children.get<sol::optional<FilePath>>("iconPath");
if (iconPath) if (iconPath)
item->setIconPath(*iconPath); item->setIconPath(*iconPath);
} }
if constexpr (hasSetIconSize<T, void (T::*)(const QSize &)>::value) { if constexpr (has_setIconSize<T>) {
const auto iconSize = children.get<sol::optional<QSize>>("iconSize"); const auto iconSize = children.get<sol::optional<QSize>>("iconSize");
if (iconSize) if (iconSize)
item->setIconSize(*iconSize); item->setIconSize(*iconSize);
} }
if constexpr (hasSetWindowFlags<T, void (T::*)(Qt::WindowFlags)>::value) { if constexpr (has_setWindowFlags<T>) {
sol::optional<sol::table> windowFlags = children.get<sol::optional<sol::table>>( sol::optional<sol::table> windowFlags = children.get<sol::optional<sol::table>>(
"windowFlags"); "windowFlags");
if (windowFlags) { if (windowFlags) {
@@ -212,13 +204,13 @@ void setProperties(std::unique_ptr<T> &item, const sol::table &children, QObject
} }
} }
if constexpr (hasSetSize<T, void (T::*)(int, int)>::value) { if constexpr (has_setSize<T>) {
sol::optional<QSize> size = children.get<sol::optional<QSize>>("size"); sol::optional<QSize> size = children.get<sol::optional<QSize>>("size");
if (size) if (size)
item->setSize(size->width(), size->height()); item->setSize(size->width(), size->height());
} }
if constexpr (hasSetWidgetAttribute<T, void (T::*)(Qt::WidgetAttribute, bool on)>::value) { if constexpr (has_setWidgetAttribute<T>) {
sol::optional<sol::table> widgetAttributes = children.get<sol::optional<sol::table>>( sol::optional<sol::table> widgetAttributes = children.get<sol::optional<sol::table>>(
"widgetAttributes"); "widgetAttributes");
if (widgetAttributes) { if (widgetAttributes) {
@@ -228,14 +220,14 @@ void setProperties(std::unique_ptr<T> &item, const sol::table &children, QObject
} }
} }
if constexpr (hasSetAutoFillBackground<T, void (T::*)(bool)>::value) { if constexpr (has_setAutoFillBackground<T>) {
sol::optional<bool> autoFillBackground = children.get<sol::optional<bool>>( sol::optional<bool> autoFillBackground = children.get<sol::optional<bool>>(
"autoFillBackground"); "autoFillBackground");
if (autoFillBackground) if (autoFillBackground)
item->setAutoFillBackground(*autoFillBackground); item->setAutoFillBackground(*autoFillBackground);
} }
if constexpr (hasOnTextChanged<T, void (T::*)(const QString &)>::value) { if constexpr (has_onTextChanged<T>) {
sol::optional<sol::protected_function> onTextChanged sol::optional<sol::protected_function> onTextChanged
= children.get<sol::optional<sol::protected_function>>("onTextChanged"); = children.get<sol::optional<sol::protected_function>>("onTextChanged");
if (onTextChanged) { if (onTextChanged) {
@@ -247,7 +239,7 @@ void setProperties(std::unique_ptr<T> &item, const sol::table &children, QObject
guard); guard);
} }
} }
if constexpr (hasOnClicked<T, void (T::*)(const std::function<void()> &, QObject *guard)>::value) { if constexpr (has_onClicked<T>) {
sol::optional<sol::protected_function> onClicked sol::optional<sol::protected_function> onClicked
= children.get<sol::optional<sol::protected_function>>("onClicked"); = children.get<sol::optional<sol::protected_function>>("onClicked");
if (onClicked) { if (onClicked) {
@@ -259,30 +251,30 @@ void setProperties(std::unique_ptr<T> &item, const sol::table &children, QObject
guard); guard);
} }
} }
if constexpr (hasSetText<T, void (T::*)(const QString &)>::value) { if constexpr (has_setText<T>) {
auto text = children.get<sol::optional<QString>>("text"); auto text = children.get<sol::optional<QString>>("text");
if (text) if (text)
item->setText(*text); item->setText(*text);
} }
if constexpr (hasSetMarkdown<T, void (T::*)(const QString &)>::value) { if constexpr (has_setMarkdown<T>) {
auto markdown = children.get<sol::optional<QString>>("markdown"); auto markdown = children.get<sol::optional<QString>>("markdown");
if (markdown) if (markdown)
item->setMarkdown(*markdown); item->setMarkdown(*markdown);
} }
if constexpr (hasSetTitle<T, void (T::*)(const QString &)>::value) { if constexpr (has_setTitle<T>) {
item->setTitle(children.get_or<QString>("title", "")); item->setTitle(children.get_or<QString>("title", ""));
} }
if constexpr (hasSetValue<T, void (T::*)(int)>::value) { if constexpr (has_setValue<T>) {
sol::optional<int> value = children.get<sol::optional<int>>("value"); sol::optional<int> value = children.get<sol::optional<int>>("value");
if (value) if (value)
item->setValue(*value); item->setValue(*value);
} }
if constexpr (hasSetReadOnly<T, void (T::*)(bool)>::value) { if constexpr (has_setReadOnly<T>) {
sol::optional<bool> readOnly = children.get<sol::optional<bool>>("readOnly"); sol::optional<bool> readOnly = children.get<sol::optional<bool>>("readOnly");
if (readOnly) if (readOnly)
item->setReadOnly(*readOnly); item->setReadOnly(*readOnly);
} }
if constexpr (hasSetOpenExternalLinks<T, void (T::*)(bool)>::value) { if constexpr (has_setOpenExternalLinks<T>) {
sol::optional<bool> openExternalLinks = children.get<sol::optional<bool>>( sol::optional<bool> openExternalLinks = children.get<sol::optional<bool>>(
"openExternalLinks"); "openExternalLinks");
if (openExternalLinks) if (openExternalLinks)