diff options
Diffstat (limited to 'src/imports/statemachine/childrenprivate.h')
-rw-r--r-- | src/imports/statemachine/childrenprivate.h | 138 |
1 files changed, 113 insertions, 25 deletions
diff --git a/src/imports/statemachine/childrenprivate.h b/src/imports/statemachine/childrenprivate.h index 57cda1c796..2dcecd6531 100644 --- a/src/imports/statemachine/childrenprivate.h +++ b/src/imports/statemachine/childrenprivate.h @@ -46,54 +46,142 @@ #include <QQmlInfo> #include <QQmlListProperty> -template <class T> -class ChildrenPrivate +enum class ChildrenMode { + None = 0x0, + State = 0x1, + Transition = 0x2, + StateOrTransition = State | Transition +}; + +template<typename T> +static T *parentObject(QQmlListProperty<QObject> *prop) { return static_cast<T *>(prop->object); } + +template<class T, ChildrenMode Mode> +struct ParentHandler { -public: - ChildrenPrivate() - {} + static bool unparentItem(QQmlListProperty<QObject> *prop, QObject *oldItem); + static bool parentItem(QQmlListProperty<QObject> *prop, QObject *item); +}; - static void append(QQmlListProperty<QObject> *prop, QObject *item) +template<class T> +struct ParentHandler<T, ChildrenMode::None> +{ + static bool unparentItem(QQmlListProperty<QObject> *, QObject *) { return true; } + static bool parentItem(QQmlListProperty<QObject> *, QObject *) { return true; } +}; + +template<class T> +struct ParentHandler<T, ChildrenMode::State> +{ + static bool parentItem(QQmlListProperty<QObject> *prop, QObject *item) + { + if (QAbstractState *state = qobject_cast<QAbstractState *>(item)) { + state->setParent(parentObject<T>(prop)); + return true; + } + return false; + } + + static bool unparentItem(QQmlListProperty<QObject> *, QObject *oldItem) + { + if (QAbstractState *state = qobject_cast<QAbstractState *>(oldItem)) { + state->setParent(nullptr); + return true; + } + return false; + } +}; + +template<class T> +struct ParentHandler<T, ChildrenMode::Transition> +{ + static bool parentItem(QQmlListProperty<QObject> *prop, QObject *item) { - QAbstractState *state = qobject_cast<QAbstractState*>(item); - if (state) { - item->setParent(prop->object); - } else { - QAbstractTransition *trans = qobject_cast<QAbstractTransition*>(item); - if (trans) - static_cast<T *>(prop->object)->addTransition(trans); + if (QAbstractTransition *trans = qobject_cast<QAbstractTransition *>(item)) { + parentObject<T>(prop)->addTransition(trans); + return true; } - static_cast<ChildrenPrivate<T>*>(prop->data)->children.append(item); - emit static_cast<T *>(prop->object)->childrenChanged(); + return false; } - static void appendNoTransition(QQmlListProperty<QObject> *prop, QObject *item) + static bool unparentItem(QQmlListProperty<QObject> *prop, QObject *oldItem) { - QAbstractState *state = qobject_cast<QAbstractState*>(item); - if (state) { - item->setParent(prop->object); + if (QAbstractTransition *trans = qobject_cast<QAbstractTransition *>(oldItem)) { + parentObject<T>(prop)->removeTransition(trans); + return true; } - static_cast<ChildrenPrivate<T>*>(prop->data)->children.append(item); - emit static_cast<T *>(prop->object)->childrenChanged(); + return false; + } +}; + +template<class T> +struct ParentHandler<T, ChildrenMode::StateOrTransition> +{ + static bool parentItem(QQmlListProperty<QObject> *prop, QObject *oldItem) + { + return ParentHandler<T, ChildrenMode::State>::parentItem(prop, oldItem) + || ParentHandler<T, ChildrenMode::Transition>::parentItem(prop, oldItem); + } + + static bool unparentItem(QQmlListProperty<QObject> *prop, QObject *oldItem) + { + return ParentHandler<T, ChildrenMode::State>::unparentItem(prop, oldItem) + || ParentHandler<T, ChildrenMode::Transition>::unparentItem(prop, oldItem); + } +}; + +template <class T, ChildrenMode Mode> +class ChildrenPrivate +{ +public: + static void append(QQmlListProperty<QObject> *prop, QObject *item) + { + Handler::parentItem(prop, item); + static_cast<Self *>(prop->data)->children.append(item); + emit parentObject<T>(prop)->childrenChanged(); } static int count(QQmlListProperty<QObject> *prop) { - return static_cast<ChildrenPrivate<T>*>(prop->data)->children.count(); + return static_cast<Self *>(prop->data)->children.count(); } static QObject *at(QQmlListProperty<QObject> *prop, int index) { - return static_cast<ChildrenPrivate<T>*>(prop->data)->children.at(index); + return static_cast<Self *>(prop->data)->children.at(index); } static void clear(QQmlListProperty<QObject> *prop) { - static_cast<ChildrenPrivate<T>*>(prop->data)->children.clear(); - emit static_cast<T *>(prop->object)->childrenChanged(); + auto &children = static_cast<Self *>(prop->data)->children; + for (QObject *oldItem : qAsConst(children)) + Handler::unparentItem(prop, oldItem); + + children.clear(); + emit parentObject<T>(prop)->childrenChanged(); + } + + static void replace(QQmlListProperty<QObject> *prop, int index, QObject *item) + { + auto &children = static_cast<Self *>(prop->data)->children; + + Handler::unparentItem(prop, children.at(index)); + Handler::parentItem(prop, item); + + children.replace(index, item); + emit parentObject<T>(prop)->childrenChanged(); + } + + static void removeLast(QQmlListProperty<QObject> *prop) + { + Handler::unparentItem(prop, static_cast<Self *>(prop->data)->children.takeLast()); + emit parentObject<T>(prop)->childrenChanged(); } private: + using Self = ChildrenPrivate<T, Mode>; + using Handler = ParentHandler<T, Mode>; + QList<QObject *> children; }; |