Skip to content

Instantly share code, notes, and snippets.

@oKcerG
Created August 11, 2020 08:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save oKcerG/9c3421631c812d5560bbb28f0743981a to your computer and use it in GitHub Desktop.
Save oKcerG/9c3421631c812d5560bbb28f0743981a to your computer and use it in GitHub Desktop.
BiBinding
#include "bibinding.h"
#include <QDebug>
QQmlProperty BiBinding::source() const
{
return m_source;
}
void BiBinding::setSource(const QQmlProperty& source)
{
if (m_source == source)
return;
m_source = source;
disconnect(m_sourceNotifyConnection);
const QMetaObject* mo = metaObject();
QMetaMethod onSourceValueChangedMetaMethod = mo->method(mo->indexOfSlot("onSourceValueChanged()"));
if (source.hasNotifySignal())
m_sourceNotifyConnection = connect(source.object(), source.property().notifySignal(), this, onSourceValueChangedMetaMethod);
else
m_sourceNotifyConnection = {};
emit sourceChanged();
}
void BiBinding::setTarget(const QQmlProperty& target)
{
if (m_target == target)
return;
m_target = target;
disconnect(m_targetNotifyConnection);
const QMetaObject* mo = metaObject();
QMetaMethod onTargetValueChangedMetaMethod = mo->method(mo->indexOfSlot("onTargetValueChanged()"));
if (target.hasNotifySignal())
m_targetNotifyConnection = connect(target.object(), target.property().notifySignal(), this, onTargetValueChangedMetaMethod);
else
m_targetNotifyConnection = {};
emit targetChanged();
}
QQmlProperty BiBinding::target() const
{
return m_target;
}
QQmlProperty BiBinding::QtProperty(QObject* object, const QString& name)
{
return QQmlProperty(object, name);
}
void BiBinding::classBegin()
{
}
void BiBinding::componentComplete()
{
onSourceValueChanged();
}
void BiBinding::onSourceValueChanged()
{
qDebug() << "onSourceValueChanged" << (m_source.isValid() && m_target.isValid()) << m_source.read() << "-->" << m_target.read();
if (m_source.isValid() && m_target.isValid())
m_target.write(m_source.read());
}
void BiBinding::onTargetValueChanged()
{
qDebug() << "onTargetValueChanged" << (m_source.isValid() && m_target.isValid()) << m_source.read() << "<--" << m_target.read();
if (m_source.isValid() && m_target.isValid()) {
QVariant targetValue = m_target.read();
m_source.write(targetValue);
QVariant sourceValue = m_source.read();
if (sourceValue != targetValue)
m_target.write(sourceValue);
}
}
#ifndef BIBINDING_H
#define BIBINDING_H
#include <QObject>
#include <QQmlProperty>
#include <QQmlParserStatus>
#include <QQmlPropertyValueSource>
#include <QQmlExpression>
class BiBinding : public QObject, public QQmlParserStatus, public QQmlPropertyValueSource
{
Q_OBJECT
Q_PROPERTY(QQmlProperty source READ source WRITE setSource NOTIFY sourceChanged)
Q_PROPERTY(QQmlProperty target READ target WRITE setTarget NOTIFY targetChanged)
public:
using QObject::QObject;
QQmlProperty source() const;
void setSource(const QQmlProperty& source);
void setTarget(const QQmlProperty& target) override;
QQmlProperty target() const;
Q_INVOKABLE QQmlProperty QtProperty(QObject* object, const QString& name);
void classBegin() override;
void componentComplete() override;
signals:
void sourceChanged();
void targetChanged();
private slots:
void onSourceValueChanged();
void onTargetValueChanged();
private:
QQmlProperty m_source;
QMetaObject::Connection m_sourceNotifyConnection;
QQmlProperty m_target;
QMetaObject::Connection m_targetNotifyConnection;
};
#endif // BIBINDING_H
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment