moc: add a helper function to set member properties

There is one minor difference: we now use operator== instead of
operator!= now, so some defective types may start working (but may break
some other, defective types).

Simplifies the emitted code, from

        case 6:
            if (_t->sMember != *reinterpret_cast< QString*>(_v)) {
                _t->sMember = *reinterpret_cast< QString*>(_v);
                Q_EMIT _t->member5Changed(_t->sMember);
            }
            break;
        case 8:
            if (_t->sub.m_string != *reinterpret_cast< QString*>(_v)) {
                _t->sub.m_string = *reinterpret_cast< QString*>(_v);
            }
            break;

to:

        case 6:
            if (QtMocHelpers::setProperty(_t->sMember, *reinterpret_cast<QString*>(_v)))
                Q_EMIT _t->member5Changed(_t->sMember);
            break;
        case 8: QtMocHelpers::setProperty(_t->sub.m_string, *reinterpret_cast<QString*>(_v)); break;

The second parameter to setProperty() helper is passed as an rvalue
reference and forwarded to the assignment, making this ready for move
semantics when moc generates code for it.

Change-Id: I45ad4a236d38f6c8f994fffd701d4193504d985a
Reviewed-by: Ahmad Samir <a.samirh78@gmail.com>
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
This commit is contained in:
Thiago Macieira 2024-09-10 14:49:34 -07:00
parent b7a47d3306
commit 2387524952
3 changed files with 25 additions and 18 deletions

View File

@ -88,6 +88,14 @@ template <typename FuncType> inline bool indexOfMethod(void **_a, FuncType f, in
return true;
}
template <typename Prop, typename Value> inline bool setProperty(Prop &property, Value &&value)
{
if (property == value)
return false;
property = std::forward<Value>(value);
return true;
}
struct NoType {};
template <typename T> struct ForceCompleteMetaTypes {};

View File

@ -1195,23 +1195,22 @@ void Generator::generateStaticMetacall()
fprintf(out, " case %d: %s%s(*reinterpret_cast< %s*>(_v)); break;\n",
propindex, prefix.constData(), p.write.constData(), p.type.constData());
} else {
fprintf(out, " case %d:\n", propindex);
fprintf(out, " if (%s%s != *reinterpret_cast< %s*>(_v)) {\n",
prefix.constData(), p.member.constData(), p.type.constData());
fprintf(out, " %s%s = *reinterpret_cast< %s*>(_v);\n",
prefix.constData(), p.member.constData(), p.type.constData());
if (!p.notify.isEmpty() && p.notifyId > -1) {
const FunctionDef &f = cdef->signalList.at(p.notifyId);
if (f.arguments.size() == 0)
fprintf(out, " Q_EMIT _t->%s();\n", p.notify.constData());
else if (f.arguments.size() == 1 && f.arguments.at(0).normalizedType == p.type)
fprintf(out, " Q_EMIT _t->%s(%s%s);\n",
p.notify.constData(), prefix.constData(), p.member.constData());
} else if (!p.notify.isEmpty() && p.notifyId < -1) {
fprintf(out, " Q_EMIT _t->%s();\n", p.notify.constData());
fprintf(out, " case %d:", propindex);
if (p.notify.isEmpty()) {
fprintf(out, " QtMocHelpers::setProperty(%s%s, *reinterpret_cast<%s*>(_v)); break;\n",
prefix.constData(), p.member.constData(), p.type.constData());
} else {
fprintf(out, "\n if (QtMocHelpers::setProperty(%s%s, *reinterpret_cast<%s*>(_v)))\n",
prefix.constData(), p.member.constData(), p.type.constData());
fprintf(out, " Q_EMIT _t->%s(", p.notify.constData());
if (p.notifyId > -1) {
const FunctionDef &f = cdef->signalList.at(p.notifyId);
if (f.arguments.size() == 1 && f.arguments.at(0).normalizedType == p.type)
fprintf(out, "%s%s", prefix.constData(), p.member.constData());
}
fprintf(out, ");\n");
fprintf(out, " break;\n");
}
fprintf(out, " }\n");
fprintf(out, " break;\n");
}
}
fprintf(out, " default: break;\n");

View File

@ -16,8 +16,8 @@ struct CustomType
QString str;
CustomType(const QString &str = QString()) : str(str) {}
operator QString() const { return str; }
friend bool operator!=(const CustomType &a, const CustomType &b)
{ return a.str != b.str; }
friend bool operator==(const CustomType &a, const CustomType &b)
{ return a.str == b.str; }
};
Q_DECLARE_METATYPE(CustomType)