summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorNicolas Werner <nicolas.werner@hotmail.de>2019-10-20 12:39:47 +0200
committerNicolas Werner <nicolas.werner@hotmail.de>2019-11-23 20:06:15 +0100
commitc37495fae29cd93b1b03e4e3689c604cc5312a18 (patch)
tree44a9fd5b0eb2c2d459ba122bd8cff739e358e4b7 /src
parentAdd native themeing to QML (where possible) (diff)
downloadnheko-c37495fae29cd93b1b03e4e3689c604cc5312a18.tar.xz
Use a basic implementation of a DelegateChooser for compat with older Qt
The interface is taken from Qt/KDE, but the implementation is different,
because the Qt implementation depends on some Qt internals.
Diffstat (limited to 'src')
-rw-r--r--src/timeline2/DelegateChooser.cpp160
-rw-r--r--src/timeline2/DelegateChooser.h78
-rw-r--r--src/timeline2/TimelineViewManager.cpp4
3 files changed, 242 insertions, 0 deletions
diff --git a/src/timeline2/DelegateChooser.cpp b/src/timeline2/DelegateChooser.cpp
new file mode 100644
index 00000000..ddde93e1
--- /dev/null
+++ b/src/timeline2/DelegateChooser.cpp
@@ -0,0 +1,160 @@
+#include "DelegateChooser.h"
+
+#include "Logging.h"
+
+// uses private API, which moved between versions
+#include <QQmlEngine>
+#include <QtGlobal>
+#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
+#include <QtQmlModels/private/qqmladaptormodel_p.h>
+#else
+#include <QtQml/private/qqmladaptormodel_p.h>
+#endif
+
+QQmlComponent *
+DelegateChoice::delegate() const
+{
+	return delegate_;
+}
+
+void
+DelegateChoice::setDelegate(QQmlComponent *delegate)
+{
+        if (delegate != delegate_) {
+                delegate_ = delegate;
+                emit delegateChanged();
+                emit changed();
+        }
+}
+
+QVariant
+DelegateChoice::roleValue() const
+{
+        return roleValue_;
+}
+
+void
+DelegateChoice::setRoleValue(const QVariant &value)
+{
+        if (value != roleValue_) {
+                roleValue_ = value;
+                emit roleValueChanged();
+                emit changed();
+        }
+}
+
+QVariant
+DelegateChooser::roleValue() const
+{
+        return roleValue_;
+}
+
+void
+DelegateChooser::setRoleValue(const QVariant &value)
+{
+        if (value != roleValue_) {
+                roleValue_ = value;
+                recalcChild();
+                emit roleValueChanged();
+        }
+}
+
+QQmlListProperty<DelegateChoice>
+DelegateChooser::choices()
+{
+        return QQmlListProperty<DelegateChoice>(this,
+                                                this,
+                                                &DelegateChooser::appendChoice,
+                                                &DelegateChooser::choiceCount,
+                                                &DelegateChooser::choice,
+                                                &DelegateChooser::clearChoices);
+}
+
+QString
+DelegateChooser::role() const
+{
+        return role_;
+}
+
+void
+DelegateChooser::setRole(const QString &role)
+{
+        if (role != role_) {
+                role_ = role;
+                emit roleChanged();
+        }
+}
+
+QQmlComponent *
+DelegateChooser::delegate(QQmlAdaptorModel *adaptorModel, int row, int column) const
+{
+        auto value = adaptorModel->value(adaptorModel->indexAt(row, column), role_);
+
+        for (const auto choice : choices_) {
+                auto choiceValue = choice->roleValue();
+                if (!value.isValid() || choiceValue == value) {
+                        nhlog::ui()->debug("Returned delegate for {}", role_.toStdString());
+                        return choice->delegate();
+                }
+        }
+
+        nhlog::ui()->debug("Returned null delegate");
+        return nullptr;
+}
+
+void
+DelegateChooser::appendChoice(QQmlListProperty<DelegateChoice> *p, DelegateChoice *c)
+{
+        DelegateChooser *dc = static_cast<DelegateChooser *>(p->object);
+        dc->choices_.append(c);
+        // dc->recalcChild();
+}
+
+int
+DelegateChooser::choiceCount(QQmlListProperty<DelegateChoice> *p)
+{
+        return static_cast<DelegateChooser *>(p->object)->choices_.count();
+}
+DelegateChoice *
+DelegateChooser::choice(QQmlListProperty<DelegateChoice> *p, int index)
+{
+        return static_cast<DelegateChooser *>(p->object)->choices_.at(index);
+}
+void
+DelegateChooser::clearChoices(QQmlListProperty<DelegateChoice> *p)
+{
+        static_cast<DelegateChooser *>(p->object)->choices_.clear();
+}
+
+void
+DelegateChooser::recalcChild()
+{
+        for (const auto choice : choices_) {
+                auto choiceValue = choice->roleValue();
+                if (!roleValue_.isValid() || !choiceValue.isValid() || choiceValue == roleValue_) {
+                        nhlog::ui()->debug("Returned delegate for {}", role_.toStdString());
+
+                        if (child) {
+                                // delete child;
+                                child = nullptr;
+                        }
+
+                        child = dynamic_cast<QQuickItem *>(
+                          choice->delegate()->create(QQmlEngine::contextForObject(this)));
+                        child->setParentItem(this);
+                        connect(this->child, &QQuickItem::heightChanged, this, [this]() {
+                                this->setHeight(this->child->height());
+                        });
+                        this->setHeight(this->child->height());
+                        return;
+                }
+        }
+}
+
+void
+DelegateChooser::componentComplete()
+{
+        QQuickItem::componentComplete();
+        recalcChild();
+}
+
diff --git a/src/timeline2/DelegateChooser.h b/src/timeline2/DelegateChooser.h
new file mode 100644
index 00000000..d2a1cf59
--- /dev/null
+++ b/src/timeline2/DelegateChooser.h
@@ -0,0 +1,78 @@
+// 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 <QQmlComponent>
+#include <QQmlListProperty>
+#include <QQuickItem>
+#include <QtCore/QObject>
+#include <QtCore/QVariant>
+
+class QQmlAdaptorModel;
+
+class DelegateChoice : public QObject
+{
+        Q_OBJECT
+        Q_CLASSINFO("DefaultProperty", "delegate")
+
+public:
+        Q_PROPERTY(QVariant roleValue READ roleValue WRITE setRoleValue NOTIFY roleValueChanged)
+        Q_PROPERTY(QQmlComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged)
+
+        QQmlComponent *delegate() const;
+        void setDelegate(QQmlComponent *delegate);
+
+        QVariant roleValue() const;
+        void setRoleValue(const QVariant &value);
+
+signals:
+        void delegateChanged();
+        void roleValueChanged();
+        void changed();
+
+private:
+        QVariant roleValue_;
+        QQmlComponent *delegate_ = nullptr;
+};
+
+class DelegateChooser : public QQuickItem
+{
+	Q_OBJECT
+	Q_CLASSINFO("DefaultProperty", "choices")
+
+public:
+        Q_PROPERTY(QQmlListProperty<DelegateChoice> choices READ choices CONSTANT)
+        Q_PROPERTY(QString role READ role WRITE setRole NOTIFY roleChanged)
+        Q_PROPERTY(QVariant roleValue READ roleValue WRITE setRoleValue NOTIFY roleValueChanged)
+
+        QQmlListProperty<DelegateChoice> choices();
+
+        QString role() const;
+        void setRole(const QString &role);
+
+        QVariant roleValue() const;
+        void setRoleValue(const QVariant &value);
+
+        QQmlComponent *delegate(QQmlAdaptorModel *adaptorModel, int row, int column = 0) const;
+
+        void recalcChild();
+        void componentComplete() override;
+
+signals:
+        void roleChanged();
+        void roleValueChanged();
+
+private:
+        QString role_;
+        QVariant roleValue_;
+        QList<DelegateChoice *> choices_;
+        QQuickItem *child;
+
+        static void appendChoice(QQmlListProperty<DelegateChoice> *, DelegateChoice *);
+        static int choiceCount(QQmlListProperty<DelegateChoice> *);
+        static DelegateChoice *choice(QQmlListProperty<DelegateChoice> *, int index);
+        static void clearChoices(QQmlListProperty<DelegateChoice> *);
+};
+
diff --git a/src/timeline2/TimelineViewManager.cpp b/src/timeline2/TimelineViewManager.cpp
index 057f03de..a054bc78 100644
--- a/src/timeline2/TimelineViewManager.cpp
+++ b/src/timeline2/TimelineViewManager.cpp
@@ -8,6 +8,7 @@
 #include <QStandardPaths>
 
 #include "ChatPage.h"
+#include "DelegateChooser.h"
 #include "Logging.h"
 #include "MxcImageProvider.h"
 #include "UserSettingsPage.h"
@@ -57,6 +58,9 @@ TimelineViewManager::TimelineViewManager(QWidget *parent)
                                          0,
                                          "MtxEvent",
                                          "Can't instantiate enum!");
+        qmlRegisterType<DelegateChoice>("com.github.nheko", 1, 0, "DelegateChoice");
+        qmlRegisterType<DelegateChooser>("com.github.nheko", 1, 0, "DelegateChooser");
+
         view      = new QQuickView();
         container = QWidget::createWindowContainer(view, parent);
         container->setMinimumSize(200, 200);