77 const QDBusConnection& con,
79 : connection(con), service(serv), path(p), interface(iface),
80 lastError(checkIfValid(serv, p, iface, isDynamic, (connectionPrivate() &&
81 connectionPrivate()->mode == QDBusConnectionPrivate::PeerMode))),
84 isValid(!lastError.isValid())
89 if (!connection.isConnected()) {
90 lastError = QDBusError(QDBusError::Disconnected,
91 QDBusUtil::disconnectedErrorMessage());
97 if (!isValid || !connection.isConnected() || !connectionPrivate()->shouldWatchService(service))
100 QObject::connect(
new QDBusServiceWatcher(service, connection, QDBusServiceWatcher::WatchForOwnerChange, q_func()),
101 SIGNAL(serviceOwnerChanged(QString,QString,QString)),
102 q_func(), SLOT(_q_serviceOwnerChanged(QString,QString,QString)));
104 currentOwner = connectionPrivate()->getNameOwner(service);
105 if (currentOwner.isEmpty())
106 lastError = connectionPrivate()->lastError;
125 QMetaType type = mp.metaType();
127 const char *expectedSignature =
"";
128 if (type.id() != QMetaType::QVariant) {
129 expectedSignature = QDBusMetaType::typeToSignature(type);
130 if (expectedSignature ==
nullptr) {
131 qWarning(
"QDBusAbstractInterface: type %s must be registered with Qt D-Bus before it can be "
132 "used to read property %s.%s",
133 mp.typeName(),
qPrintable(interface), mp.name());
134 lastError = QDBusError(QDBusError::Failed,
"Unregistered type %1 cannot be handled"_L1
135 .arg(QLatin1StringView(mp.typeName())));
141 QDBusMessage msg = QDBusMessage::createMethodCall(service, path,
142 QDBusUtil::dbusInterfaceProperties(),
145 msg << interface << QString::fromUtf8(mp.name());
146 QDBusMessage reply = connection.call(msg, QDBus::Block, timeout);
148 if (reply.type() != QDBusMessage::ReplyMessage) {
149 lastError = QDBusError(reply);
152 if (reply.signature() !=
"v"_L1) {
155 lastError = QDBusError(QDBusError::InvalidSignature, std::move(errmsg).arg(reply.signature()));
159 QByteArray foundSignature;
160 const char *foundType =
nullptr;
161 QVariant value = qvariant_cast<QDBusVariant>(reply.arguments().at(0)).variant();
163 if (value.metaType() == type || type.id() == QMetaType::QVariant
164 || (expectedSignature[0] ==
'v' && expectedSignature[1] ==
'\0')) {
166 if (type.id() == QMetaType::QVariant) {
167 *
reinterpret_cast<QVariant*>(returnValuePtr) = value;
169 QMetaType(type).destruct(returnValuePtr);
170 QMetaType(type).construct(returnValuePtr, value.constData());
175 if (value.metaType() == QMetaType::fromType<QDBusArgument>()) {
178 foundType =
"user type";
179 foundSignature = arg.currentSignature().toLatin1();
180 if (foundSignature == expectedSignature) {
182 return QDBusMetaType::demarshall(arg, QMetaType(type), returnValuePtr);
185 foundType = value.typeName();
186 foundSignature = QDBusMetaType::typeToSignature(value.metaType());
190 const auto errmsg =
"Unexpected '%1' (%2) when retrieving property '%3.%4' "
191 "(expected type '%5' (%6))"_L1;
192 lastError = QDBusError(QDBusError::InvalidSignature,
193 errmsg.arg(QLatin1StringView(foundType),
194 QLatin1StringView(foundSignature),
196 QLatin1StringView(mp.name()),
197 QLatin1StringView(mp.typeName()),
198 QLatin1StringView(expectedSignature)));
208 QDBusMessage msg = QDBusMessage::createMethodCall(service, path,
209 QDBusUtil::dbusInterfaceProperties(),
212 msg << interface << QString::fromUtf8(mp.name()) << QVariant::fromValue(QDBusVariant(value));
213 QDBusMessage reply = connection.call(msg, QDBus::Block, timeout);
215 if (reply.type() != QDBusMessage::ReplyMessage) {
216 lastError = QDBusError(reply);
237int QDBusAbstractInterfaceBase::qt_metacall(QMetaObject::Call _c,
int _id,
void **_a)
240 _id = QObject::qt_metacall(_c, _id, _a);
244 if (_c == QMetaObject::ReadProperty || _c == QMetaObject::WriteProperty) {
245 QMetaProperty mp = metaObject()->property(saved_id);
246 int &status = *
reinterpret_cast<
int *>(_a[2]);
248 if (_c == QMetaObject::WriteProperty) {
250 if (mp.metaType() == QMetaType::fromType<QDBusVariant>())
251 value =
reinterpret_cast<
const QDBusVariant*>(_a[0])->variant();
253 value = QVariant(mp.metaType(), _a[0]);
254 status = d_func()->setProperty(mp, value) ? 1 : 0;
256 bool readStatus = d_func()->property(mp, _a[0]);
259 if (!readStatus && _a[1]) {
261 reinterpret_cast<QVariant*>(_a[1])->clear();
302QDBusAbstractInterface::QDBusAbstractInterface(
const QString &service,
const QString &path,
303 const char *interface,
const QDBusConnection &con,
305 : QDBusAbstractInterfaceBase(*
new QDBusAbstractInterfacePrivate(service, path, QString::fromLatin1(interface),
309 d_func()->initOwnerTracking();
455QDBusMessage QDBusAbstractInterface::callWithArgumentList(QDBus::CallMode mode,
456 const QString& method,
457 const QList<QVariant>& args)
459 Q_D(QDBusAbstractInterface);
461 if (!d->isValid || !d->canMakeCalls())
462 return QDBusMessage::createError(d->lastError);
466 int pos = method.indexOf(u'.');
470 if (mode == QDBus::AutoDetect) {
473 const QMetaObject *mo = metaObject();
474 QByteArray match = m.toLatin1();
476 for (
int i = staticMetaObject.methodCount(); i < mo->methodCount(); ++i) {
477 QMetaMethod mm = mo->method(i);
478 if (mm.name() == match) {
483 QList<QByteArray> tags = QByteArray(mm.tag()).split(
' ');
484 if (tags.contains(
"Q_NOREPLY"))
485 mode = QDBus::NoBlock;
493 QDBusMessage msg = QDBusMessage::createMethodCall(service(), path(), interface(), m);
494 QDBusMessagePrivate::setParametersValidated(msg,
true);
495 msg.setArguments(args);
497 QDBusMessage reply = d->connection.call(msg, mode, d->timeout);
498 if (thread() == QThread::currentThread())
499 d->lastError = QDBusError(reply);
502 if (reply.arguments().isEmpty())
522QDBusPendingCall QDBusAbstractInterface::asyncCallWithArgumentList(
const QString& method,
523 const QList<QVariant>& args)
525 Q_D(QDBusAbstractInterface);
527 if (!d->isValid || !d->canMakeCalls())
528 return QDBusPendingCall::fromError(d->lastError);
530 QDBusMessage msg = QDBusMessage::createMethodCall(service(), path(), interface(), method);
531 QDBusMessagePrivate::setParametersValidated(msg,
true);
532 msg.setArguments(args);
533 if (d->interactiveAuthorizationAllowed)
534 msg.setInteractiveAuthorizationAllowed(
true);
535 return d->connection.asyncCall(msg, d->timeout);
562bool QDBusAbstractInterface::callWithCallback(
const QString &method,
563 const QList<QVariant> &args,
565 const char *returnMethod,
566 const char *errorMethod)
568 Q_D(QDBusAbstractInterface);
570 if (!d->isValid || !d->canMakeCalls())
573 QDBusMessage msg = QDBusMessage::createMethodCall(service(),
577 QDBusMessagePrivate::setParametersValidated(msg,
true);
578 msg.setArguments(args);
580 d->lastError = QDBusError();
581 return d->connection.callWithCallback(msg,
618void QDBusAbstractInterface::connectNotify(
const QMetaMethod &signal)
621 Q_D(QDBusAbstractInterface);
626 static const QMetaMethod destroyedSignal = QMetaMethod::fromSignal(&QDBusAbstractInterface::destroyed);
627 if (signal == destroyedSignal)
630 QDBusConnectionPrivate *conn = d->connectionPrivate();
632 conn->connectRelay(d->service, d->path, d->interface,
659 QDBusAbstractInterfacePrivate *d = ptr->d_func();
660 QDBusConnectionPrivate *conn = d->connectionPrivate();
664 const QMetaObject *mo = ptr->metaObject();
665 QMetaMethod signal = signalId >= 0 ? mo->method(signalId) : QMetaMethod();
666 if (signal.isValid()) {
667 if (!ptr->isSignalConnected(signal))
668 return conn->disconnectRelay(d->service, d->path, d->interface,
673 int midx = QObject::staticMetaObject.methodCount();
674 const int end = mo->methodCount();
675 for ( ; midx < end; ++midx) {
676 QMetaMethod mm = mo->method(midx);
677 if (mm.methodType() == QMetaMethod::Signal && !ptr->isSignalConnected(mm))
678 conn->disconnectRelay(d->service, d->path, d->interface, ptr, mm);
806QDBusMessage QDBusAbstractInterface::doCall(QDBus::CallMode mode,
const QString &method,
const QVariant *args, size_t numArgs)
815QDBusPendingCall QDBusAbstractInterface::doAsyncCall(
const QString &method,
const QVariant *args, size_t numArgs)