Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qqmlnotifier.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant
4
7#include <QtCore/qdebug.h>
8#include <private/qthread_p.h>
9
11
12typedef void (*Callback)(QQmlNotifierEndpoint *, void **);
13
20
30
31namespace {
32 struct NotifyListTraversalData {
33 NotifyListTraversalData(QQmlNotifierEndpoint *ep = nullptr)
34 : originalSenderPtr(0)
35 , disconnectWatch(nullptr)
36 , endpoint(ep)
37 {}
38
39 qintptr originalSenderPtr;
40 qintptr *disconnectWatch;
41 QQmlNotifierEndpoint *endpoint;
42 };
43}
44
45void QQmlNotifier::notify(QQmlData *ddata, int notifierIndex)
46{
47 if (QQmlNotifierEndpoint *ep = ddata->notify(notifierIndex))
48 emitNotify(ep, nullptr);
49}
50
51void QQmlNotifier::emitNotify(QQmlNotifierEndpoint *endpoint, void **a)
52{
53 QVarLengthArray<NotifyListTraversalData> stack;
54 while (endpoint) {
55 stack.append(NotifyListTraversalData(endpoint));
56 endpoint = endpoint->next;
57 }
58
59 int i = 0;
60 for (; i < stack.size(); ++i) {
61 NotifyListTraversalData &data = stack[i];
62
63 if (!data.endpoint->isNotifying()) {
64 data.endpoint->startNotifying(&data.originalSenderPtr);
65 data.disconnectWatch = &data.originalSenderPtr;
66 } else {
67 data.disconnectWatch = (qintptr *)(data.endpoint->senderPtr & ~0x1);
68 }
69 }
70
71 while (--i >= 0) {
72 NotifyListTraversalData &data = stack[i];
73 if (*data.disconnectWatch) {
74 Q_ASSERT(QQmlNotifier_callbacks[data.endpoint->callback]);
75 QQmlNotifier_callbacks[data.endpoint->callback](data.endpoint, a);
76 if (data.disconnectWatch == &data.originalSenderPtr && data.originalSenderPtr) {
77 data.endpoint->stopNotifying(&data.originalSenderPtr);
78 }
79 }
80 }
81}
82
83/*! \internal
84 \a sourceSignal MUST be in the signal index range (see QObjectPrivate::signalIndex()).
85 This is different from QMetaMethod::methodIndex().
86*/
87void QQmlNotifierEndpoint::connect(QObject *source, int sourceSignal, QQmlEngine *engine, bool doNotify)
88{
90
91 Q_ASSERT(engine);
92 if (QObjectPrivate::get(source)->threadData.loadRelaxed()->threadId.loadRelaxed() !=
93 QObjectPrivate::get(engine)->threadData.loadRelaxed()->threadId.loadRelaxed()) {
94
95 QString sourceName;
96 QDebug(&sourceName) << source;
97 sourceName = sourceName.left(sourceName.size() - 1);
98 QString engineName;
99 QDebug(&engineName).nospace() << engine;
100 engineName = engineName.left(engineName.size() - 1);
101
102 qFatal("QQmlEngine: Illegal attempt to connect to %s that is in"
103 " a different thread than the QML engine %s.", qPrintable(sourceName),
104 qPrintable(engineName));
105 }
106
107 setSender(qintptr(source));
108 this->sourceSignal = sourceSignal;
109 QQmlPropertyPrivate::flushSignal(source, sourceSignal);
110 QQmlData *ddata = QQmlData::get(source, true);
111 ddata->addNotify(sourceSignal, this);
112 if (doNotify) {
113 needsConnectNotify = doNotify;
114 QObjectPrivate * const priv = QObjectPrivate::get(source);
115 priv->connectNotify(QMetaObjectPrivate::signal(source->metaObject(), sourceSignal));
116 }
117}
118
119QT_END_NAMESPACE
Combined button and popup list for selecting options.
void QQmlUnbindableToUnbindableGuard_callback(QQmlNotifierEndpoint *, void **)
void QQmlVMEMetaObjectEndpoint_callback(QQmlNotifierEndpoint *, void **)
void QQmlBoundSignal_callback(QQmlNotifierEndpoint *, void **)
void QQmlUnbindableToBindableGuard_callback(QQmlNotifierEndpoint *, void **)
QT_BEGIN_NAMESPACE typedef void(* Callback)(QQmlNotifierEndpoint *, void **)
void QQmlDirtyReferenceObject_callback(QQmlNotifierEndpoint *, void **)
void QQmlJavaScriptExpressionGuard_callback(QQmlNotifierEndpoint *, void **)
static Callback QQmlNotifier_callbacks[]