summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMathias Hasselmann <mathias.hasselmann@kdab.com>2013-11-14 00:43:03 +0100
committerMathias Hasselmann <mathias.hasselmann@kdab.com>2013-11-14 00:43:03 +0100
commit37ac24f73170070b69413fb83eeef64d980f3e6a (patch)
tree875b6b8b73c038d20c47f9aa88a867b9f20558dc
parent1242fbb5f9eba7e7965ece5006672468374b5747 (diff)
downloadqtquickstreamer-37ac24f73170070b69413fb83eeef64d980f3e6a.tar.gz
qtquickstreamer-37ac24f73170070b69413fb83eeef64d980f3e6a.tar.xz
Start to handle signals properly
-rw-r--r--src/QuickStreamer/item.cpp83
-rw-r--r--src/QuickStreamer/item.h2
2 files changed, 61 insertions, 24 deletions
diff --git a/src/QuickStreamer/item.cpp b/src/QuickStreamer/item.cpp
index 9a716fd..a521241 100644
--- a/src/QuickStreamer/item.cpp
+++ b/src/QuickStreamer/item.cpp
@@ -74,6 +74,38 @@ struct PropertyDelegate
ResetDelegate reset;
};
+struct SignalDelegate
+{
+ typedef std::function<void()> SignalClosure;
+
+ static void invokeClosure(void *data)
+ {
+ (*static_cast<SignalClosure *>(data))();
+ }
+
+ static void deleteClosure(void *data, GClosure *)
+ {
+ delete static_cast<SignalClosure *>(data);
+ }
+
+ void connect(Item *item) const
+ {
+ const int signalIndex = methodId;
+
+ auto closure = new SignalClosure([item, signalIndex] {
+ QMetaObject::activate(item, signalIndex, Q_NULLPTR); // FIXME: deal with signal arguments
+ });
+
+ g_signal_connect_data(item->target(), name.constData(),
+ G_CALLBACK(&SignalDelegate::invokeClosure), closure,
+ &SignalDelegate::deleteClosure,
+ G_CONNECT_SWAPPED);
+ }
+
+ QByteArray name;
+ int methodId;
+};
+
static bool isDash(char ch)
{
return ch == '-' || ch == '_';
@@ -553,15 +585,23 @@ struct TypeInfo
const QByteArray &propertyType,
QMetaObjectBuilder *objectBuilder)
{
- auto notifierBuilder = objectBuilder->addSignal(propertyName + QByteArrayLiteral("Changed()"));
- auto propertyBuilder = objectBuilder->addProperty(propertyName, propertyType, notifierBuilder.index());
+ int notifierIndex = -1;
+
+ if (delegate.spec) {
+ auto notifier = objectBuilder->addSignal(propertyName + QByteArrayLiteral("Changed()"));
+ signalDelegates.append({ QByteArrayLiteral("notify::") + delegate.spec->name,
+ parent->metaObject->methodCount() + notifier.index() });
+ notifierIndex = notifier.index();
+ }
+
+ auto property = objectBuilder->addProperty(propertyName, propertyType, notifierIndex);
- propertyBuilder.setReadable(delegate.read != Q_NULLPTR);
- propertyBuilder.setWritable(delegate.write != Q_NULLPTR);
- propertyBuilder.setResettable(delegate.reset != Q_NULLPTR);
+ property.setReadable(delegate.read != Q_NULLPTR);
+ property.setWritable(delegate.write != Q_NULLPTR);
+ property.setResettable(delegate.reset != Q_NULLPTR);
if (propertyType.endsWith(ENUMERATOR_TYPE_SUFFIX)) { // FIXME
- propertyBuilder.setEnumOrFlag(true);
+ property.setEnumOrFlag(true);
const auto &scopeName = propertyType.left(propertyType.length() - ENUMERATOR_TYPE_SUFFIX.length());
const int scopeId = QMetaType::type(scopeName.constData());
@@ -785,20 +825,18 @@ struct TypeInfo
return id - propertyDelegates.size();
}
- void emitPropertyChanged(Item *object, const GParamSpec *pspec) const
+ int connectSignal(Item *item, int id) const
{
- for (int i = 0; i < propertyDelegates.size(); ++i) {
- auto const &p = propertyDelegates.at(i);
+ if (parent)
+ id = parent->connectSignal(item, id);
- // can compare by pointer because GParamSpec::name is interned
- if (p.spec && pspec->name == p.spec->name) {
- QMetaObject::activate(object, metaObject, i, Q_NULLPTR);
- return;
- }
- }
+ if (id < 0)
+ return id;
- if (parent)
- parent->emitPropertyChanged(object, pspec);
+ if (id < signalDelegates.size())
+ signalDelegates.at(id).connect(item);
+
+ return id - signalDelegates.size();
}
const TypeInfo *parent;
@@ -806,6 +844,8 @@ struct TypeInfo
QByteArray elementName;
QVector<PropertyDelegate> propertyDelegates;
+ QVector<SignalDelegate> signalDelegates;
+
static QHash<GType, TypeInfo *> cache;
};
@@ -826,9 +866,6 @@ Item::Item(GstObject *target, QObject *parent)
g_object_ref_sink(m_target);
g_object_set_qdata(G_OBJECT(m_target), ITEM_DATA_QUARK, this);
-
- auto notifyCallback = reinterpret_cast<GCallback>(&Item::emitPropertyChanged);
- g_signal_connect_swapped(target, "notify", notifyCallback, this);
}
Item::Item(const Item &other)
@@ -953,10 +990,10 @@ GstObject *Item::target() const
return m_target;
}
-void Item::emitPropertyChanged(Item *self, GParamSpec *pspec)
+void Item::connectNotify(const QMetaMethod &signal)
{
- const auto *const typeInfo = TypeInfo::find(G_OBJECT_TYPE(self->m_target));
- typeInfo->emitPropertyChanged(self, pspec);
+ const int signalIndex = signal.methodIndex() - QObject::staticMetaObject.methodCount();
+ TypeInfo::find(G_OBJECT_TYPE(m_target))->connectSignal(this, signalIndex);
}
} // namespace QQuickStreamer
diff --git a/src/QuickStreamer/item.h b/src/QuickStreamer/item.h
index 2a2830c..99ba21d 100644
--- a/src/QuickStreamer/item.h
+++ b/src/QuickStreamer/item.h
@@ -57,7 +57,7 @@ public:
GstObject *target() const;
protected:
- static void emitPropertyChanged(Item *self, GParamSpec *pspec);
+ void connectNotify(const QMetaMethod &signal) Q_DECL_OVERRIDE;
private:
GstObject *const m_target;