summary refs log tree commit diff
path: root/src/timeline/EventDelegateChooser.h
blob: b627b3835c58110dae3917ddbdb08312cdff902b (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
// SPDX-FileCopyrightText: Nheko Contributors
//
// SPDX-License-Identifier: GPL-3.0-or-later

// A DelegateChooser like the one, that was added to Qt5.12 (in labs), but compatible with older Qt
// versions see KDE/kquickitemviews see qtdeclarative/qqmldelagatecomponent

#pragma once

#include <QAbstractItemModel>
#include <QQmlComponent>
#include <QQmlIncubator>
#include <QQmlListProperty>
#include <QQuickItem>
#include <QtCore/QObject>
#include <QtCore/QVariant>

#include "TimelineModel.h"

class EventDelegateChoice : public QObject
{
    Q_OBJECT
    QML_ELEMENT
    Q_CLASSINFO("DefaultProperty", "delegate")

public:
    Q_PROPERTY(QList<int> roleValues READ roleValues WRITE setRoleValues NOTIFY roleValuesChanged
                 REQUIRED FINAL)
    Q_PROPERTY(
      QQmlComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged REQUIRED FINAL)

    [[nodiscard]] QQmlComponent *delegate() const;
    void setDelegate(QQmlComponent *delegate);

    [[nodiscard]] QList<int> roleValues() const;
    void setRoleValues(const QList<int> &value);

signals:
    void delegateChanged();
    void roleValuesChanged();
    void changed();

private:
    QList<int> roleValues_;
    QQmlComponent *delegate_ = nullptr;
};

class EventDelegateChooser : public QQuickItem
{
    Q_OBJECT
    QML_ELEMENT
    Q_CLASSINFO("DefaultProperty", "choices")

public:
    Q_PROPERTY(QQmlListProperty<EventDelegateChoice> choices READ choices CONSTANT FINAL)
    Q_PROPERTY(QQuickItem *main READ main NOTIFY mainChanged FINAL)
    Q_PROPERTY(QQuickItem *reply READ reply NOTIFY replyChanged FINAL)
    Q_PROPERTY(TimelineModel *room READ room WRITE setRoom NOTIFY roomChanged REQUIRED FINAL)
    Q_PROPERTY(QString eventId READ eventId WRITE setEventId NOTIFY eventIdChanged REQUIRED FINAL)
    Q_PROPERTY(QString replyTo READ replyTo WRITE setReplyTo NOTIFY replyToChanged REQUIRED FINAL)

    QQmlListProperty<EventDelegateChoice> choices();

    [[nodiscard]] QQuickItem *main() const
    {
        return qobject_cast<QQuickItem *>(eventIncubator.object());
    }
    [[nodiscard]] QQuickItem *reply() const
    {
        return qobject_cast<QQuickItem *>(replyIncubator.object());
    }

    void setRoom(TimelineModel *m)
    {
        if (m != room_) {
            room_ = m;
            eventIncubator.reset(eventId_);
            replyIncubator.reset(replyId);
            emit roomChanged();
        }
    }
    [[nodiscard]] TimelineModel *room() { return room_; }

    void setEventId(QString idx)
    {
        eventId_ = idx;
        emit eventIdChanged();
    }
    [[nodiscard]] QString eventId() const { return eventId_; }
    void setReplyTo(QString id)
    {
        replyId = id;
        emit replyToChanged();
    }
    [[nodiscard]] QString replyTo() const { return replyId; }

    void componentComplete() override;

signals:
    void mainChanged();
    void replyChanged();
    void roomChanged();
    void eventIdChanged();
    void replyToChanged();

private:
    struct DelegateIncubator final : public QQmlIncubator
    {
        DelegateIncubator(EventDelegateChooser &parent, bool forReply)
          : QQmlIncubator(QQmlIncubator::AsynchronousIfNested)
          , chooser(parent)
          , forReply(forReply)
        {
        }
        void setInitialState(QObject *object) override;
        void statusChanged(QQmlIncubator::Status status) override;

        void reset(QString id);

        EventDelegateChooser &chooser;
        bool forReply;
        QString currentId;

        QString instantiatedId;
        int instantiatedRole = -1;
        QAbstractItemModel *instantiatedModel = nullptr;
    };

    QVariant roleValue_;
    QList<EventDelegateChoice *> choices_;
    DelegateIncubator eventIncubator{*this, false};
    DelegateIncubator replyIncubator{*this, true};
    TimelineModel *room_{nullptr};
    QString eventId_;
    QString replyId;

    static void appendChoice(QQmlListProperty<EventDelegateChoice> *, EventDelegateChoice *);
    static qsizetype choiceCount(QQmlListProperty<EventDelegateChoice> *);
    static EventDelegateChoice *choice(QQmlListProperty<EventDelegateChoice> *, qsizetype index);
    static void clearChoices(QQmlListProperty<EventDelegateChoice> *);
};