Помощник препроцессора для правильного отображения перечисления как Q_PROPERTYs - PullRequest
0 голосов
/ 06 августа 2020

В моем приложении QML есть бэкэнд для получения сообщений (в формате: id + data), и я показываю его QML как Q_PROPERTIES.

Проблема в том, что после увеличения количества MyMsg с 10 до ~ 200 я получил много нечистоты и безумно сложный в обслуживании код.

Я нашел способ использовать препроцессор и очистил его, но все еще есть возможности для улучшения (я думаю), но я не могу этого понять. Текущий код (максимально упрощенный):

typedef enum
{
    Msg1 = 1,
    SomeMsg = 12,
    SomeOtherMsg = 123,
    moreOfThose = 9999
} MyMsg;

#define AUTO_PROPERTY(TYPE, NAME)                                        \
    Q_PROPERTY(                                                          \
        TYPE NAME READ get_##NAME WRITE set_##NAME NOTIFY notify_##NAME) \
public:                                                                  \
    TYPE get_##NAME() const                                              \
    {                                                                    \
        return a_##NAME;                                                 \
    }                                                                    \
    void set_##NAME(const TYPE &value)                                   \
    {                                                                    \
        if (a_##NAME == value)                                           \
            return;                                                      \
        a_##NAME = value;                                                \
        emit notify_##NAME(value);                                       \
    }                                                                    \
    Q_SIGNAL void notify_##NAME(TYPE value);                             \
                                                                         \
private:                                                                 \
    TYPE a_##NAME;

#define CASE_PROPERTY(NAME, PARAM) \
    case NAME:                     \
        set_##NAME(PARAM);         \
        break;

class Backend {
    AUTO_PROPERTY(QString, Msg1)
    AUTO_PROPERTY(QString, SomeMsg)
    AUTO_PROPERTY(QString, SomeOtherMsg)
    AUTO_PROPERTY(QString, moreOfThose)

public:
    Backend(){};

private:
    void parse(MyMsg msg, int value)
    {
        switch (msg)
        {
            CASE_PROPERTY(Msg1, value);
            CASE_PROPERTY(SomeMsg, value);
            CASE_PROPERTY(SomeOtherMsg, value);
            CASE_PROPERTY(moreOfThose, value);
        }
    }
}

Я бы хотел увидеть что-то вроде:

class Backend {
    AUTO_PROPERTIES(MyMsg)

public:
    Backend(){};

private:
    void parse(MyMsg msg, int value)
    {
        switch (msg)
        {
            CASE_PROPERTIES(MyMsg)
        }
    }
}

Примечание: файл с перечислением является внешним (общим) заголовком. Можно улучшить, но в целом его не следует изменять.

Примечание 2: чтобы разрешить двунаправленную связь в QML, он уже заключен в оболочку, хотя, кажется, не имеет отношения к случаю

namespace ABC {
Q_NAMESPACE
#include "../common/mymsg.hpp"
Q_ENUM_NS(MyMsg)
} // namespace ABC

Любой подсказка, чтобы помочь мне разобраться?

...