95 xml_data +=
"<node>\n"_L1;
98 Q_ASSERT_X(QThread::currentThread() == node.obj->thread(),
99 "QDBusConnection: internal threading error",
100 "function called for an object that is in another thread!!");
102 if (node.flags & (QDBusConnection::ExportScriptableContents
103 | QDBusConnection::ExportNonScriptableContents)) {
105 const QMetaObject *mo = node.obj->metaObject();
106 for ( ; mo != &QObject::staticMetaObject; mo = mo->superClass())
107 xml_data += qDBusGenerateMetaObjectXml(node.interfaceName, mo, mo->superClass(),
113 if (node.flags & QDBusConnection::ExportAdaptors &&
114 (connector = qDBusFindAdaptorConnector(node.obj))) {
117 for (
const QDBusAdaptorConnector::AdaptorData &adaptorData :
118 std::as_const(connector->adaptors)) {
121 QDBusAbstractAdaptorPrivate::retrieveIntrospectionXml(adaptorData.adaptor);
122 if (ifaceXml.isEmpty()) {
124 ifaceXml += qDBusGenerateMetaObjectXml(
125 QString::fromLatin1(adaptorData.interface),
126 adaptorData.adaptor->metaObject(),
127 &QDBusAbstractAdaptor::staticMetaObject,
128 QDBusConnection::ExportScriptableContents
129 | QDBusConnection::ExportNonScriptableContents);
131 QDBusAbstractAdaptorPrivate::saveIntrospectionXml(adaptorData.adaptor,
135 xml_data += ifaceXml;
140 if (node.flags & QDBusConnectionPrivate::VirtualObject) {
141 xml_data += node.treeNode->introspect(path);
150 if (node.flags & QDBusConnection::ExportChildObjects) {
151 xml_data += generateSubObjectXml(node.obj);
154 for (
const QDBusConnectionPrivate::ObjectTreeNode &node : node.children) {
155 if (node.obj || !node.children.isEmpty())
156 xml_data +=
" <node name=\""_L1 + node.name +
"\"/>\n"_L1;
160 xml_data +=
"</node>\n"_L1;
185 const QDBusMessage &msg)
187 Q_ASSERT(msg.arguments().size() == 2);
188 Q_ASSERT_X(!node.obj || QThread::currentThread() == node.obj->thread(),
189 "QDBusConnection: internal threading error",
190 "function called for an object that is in another thread!!");
192 QString interface_name = msg.arguments().at(0).toString();
193 QByteArray property_name = msg.arguments().at(1).toString().toUtf8();
197 bool interfaceFound =
false;
198 if (node.flags & QDBusConnection::ExportAdaptors &&
199 (connector = qDBusFindAdaptorConnector(node.obj))) {
203 if (interface_name.isEmpty()) {
204 for (
const QDBusAdaptorConnector::AdaptorData &adaptorData : connector->adaptors) {
205 const QMetaObject *mo = adaptorData.adaptor->metaObject();
206 int pidx = mo->indexOfProperty(property_name);
208 value = mo->property(pidx).read(adaptorData.adaptor);
213 QDBusAdaptorConnector::AdaptorMap::ConstIterator it;
216 if (it != connector
->adaptors.constEnd() && interface_name == QLatin1StringView(it->interface)) {
217 interfaceFound =
true;
218 value = it->adaptor->property(property_name);
223 if (!interfaceFound && !value.isValid()
224 && node.flags & (QDBusConnection::ExportAllProperties |
225 QDBusConnection::ExportNonScriptableProperties)) {
227 if (!interface_name.isEmpty())
228 interfaceFound = qDBusInterfaceInObject(node.obj, interface_name);
230 if (interfaceFound) {
231 int pidx = node.obj->metaObject()->indexOfProperty(property_name);
233 QMetaProperty mp = node.obj->metaObject()->property(pidx);
234 if ((mp.isScriptable() && (node.flags & QDBusConnection::ExportScriptableProperties)) ||
235 (!mp.isScriptable() && (node.flags & QDBusConnection::ExportNonScriptableProperties)))
236 value = mp.read(node.obj);
241 if (!value.isValid()) {
244 return interfaceNotFoundError(msg, interface_name);
245 return propertyNotFoundError(msg, interface_name, property_name);
248 return msg.createReply(QVariant::fromValue(QDBusVariant(value)));
260 const QByteArray &property_name,
int status)
263 case PropertyNotFound:
264 return propertyNotFoundError(msg, interface_name, property_name);
265 case PropertyTypeMismatch:
266 return msg.createErrorReply(QDBusError::InvalidArgs,
267 "Invalid arguments for writing to property %1%2%3"_L1
269 interface_name.isEmpty() ?
""_L1 :
"."_L1,
270 QLatin1StringView(property_name)));
271 case PropertyReadOnly:
272 return msg.createErrorReply(QDBusError::PropertyReadOnly,
273 "Property %1%2%3 is read-only"_L1
275 interface_name.isEmpty() ?
""_L1 :
"."_L1,
276 QLatin1StringView(property_name)));
277 case PropertyWriteFailed:
278 return msg.createErrorReply(QDBusError::InternalError,
279 QString::fromLatin1(
"Internal error"));
282 return msg.createReply();
284 Q_ASSERT_X(
false,
"",
"Should not be reached");
285 return QDBusMessage();
288static int writeProperty(QObject *obj,
const QByteArray &property_name, QVariant value,
291 const QMetaObject *mo = obj->metaObject();
292 int pidx = mo->indexOfProperty(property_name);
298 QMetaProperty mp = mo->property(pidx);
301 if (!mp.isWritable())
305 bool isScriptable = mp.isScriptable();
306 if (!(propFlags & QDBusConnection::ExportScriptableProperties) && isScriptable)
308 if (!(propFlags & QDBusConnection::ExportNonScriptableProperties) && !isScriptable)
313 QMetaType id = mp.metaType();
316 qWarning(
"QDBusConnection: Unable to handle unregistered datatype '%s' for property '%s::%s'",
317 mp.typeName(), mo->className(), property_name.constData());
321 if (id.id() != QMetaType::QVariant && value.metaType() == QDBusMetaTypeId::argument()) {
323 QVariant other{QMetaType(id)};
324 if (!QDBusMetaType::demarshall(qvariant_cast<QDBusArgument>(value), other.metaType(), other.data())) {
325 qWarning(
"QDBusConnection: type '%s' (%d) is not registered with QtDBus. "
326 "Use qDBusRegisterMetaType to register it",
327 mp.typeName(), id.id());
331 value =
std::move(other);
334 if (mp.metaType() == QMetaType::fromType<QDBusVariant>())
335 value = QVariant::fromValue(QDBusVariant(value));
342 const QDBusMessage &msg)
344 Q_ASSERT(msg.arguments().size() == 3);
345 Q_ASSERT_X(!node.obj || QThread::currentThread() == node.obj->thread(),
346 "QDBusConnection: internal threading error",
347 "function called for an object that is in another thread!!");
349 QString interface_name = msg.arguments().at(0).toString();
350 QByteArray property_name = msg.arguments().at(1).toString().toUtf8();
351 QVariant value = qvariant_cast<QDBusVariant>(msg.arguments().at(2)).variant();
354 if (node.flags & QDBusConnection::ExportAdaptors &&
355 (connector = qDBusFindAdaptorConnector(node.obj))) {
359 if (interface_name.isEmpty()) {
360 for (
const QDBusAdaptorConnector::AdaptorData &adaptorData :
361 std::as_const(connector->adaptors)) {
362 int status = writeProperty(adaptorData.adaptor, property_name, value);
363 if (status == PropertyNotFound)
365 return propertyWriteReply(msg, interface_name, property_name, status);
368 QDBusAdaptorConnector::AdaptorMap::ConstIterator it;
371 if (it != connector
->adaptors.cend() && interface_name == QLatin1StringView(it->interface)) {
372 return propertyWriteReply(msg, interface_name, property_name,
373 writeProperty(it->adaptor, property_name, value));
378 if (node.flags & (QDBusConnection::ExportScriptableProperties |
379 QDBusConnection::ExportNonScriptableProperties)) {
381 bool interfaceFound =
true;
382 if (!interface_name.isEmpty())
383 interfaceFound = qDBusInterfaceInObject(node.obj, interface_name);
385 if (interfaceFound) {
386 return propertyWriteReply(msg, interface_name, property_name,
387 writeProperty(node.obj, property_name, value, node.flags));
392 if (!interface_name.isEmpty())
393 return interfaceNotFoundError(msg, interface_name);
394 return propertyWriteReply(msg, interface_name, property_name, PropertyNotFound);
408 const QMetaObject *mo = object->metaObject();
411 for (
int i = QObject::staticMetaObject.propertyCount(); i < mo->propertyCount(); ++i) {
412 QMetaProperty mp = mo->property(i);
415 if (!mp.isReadable())
419 QMetaType type = mp.metaType();
422 const char *signature = QDBusMetaType::typeToSignature(type);
427 if ((mp.isScriptable() && flags & QDBusConnection::ExportScriptableProperties) ||
428 (!mp.isScriptable() && flags & QDBusConnection::ExportNonScriptableProperties)) {
430 QVariant value = mp.read(object);
432 result.insert(QString::fromLatin1(mp.name()), value);
440 const QDBusMessage &msg)
442 Q_ASSERT(msg.arguments().size() == 1);
443 Q_ASSERT_X(!node.obj || QThread::currentThread() == node.obj->thread(),
444 "QDBusConnection: internal threading error",
445 "function called for an object that is in another thread!!");
447 QString interface_name = msg.arguments().at(0).toString();
449 bool interfaceFound =
false;
453 if (node.flags & QDBusConnection::ExportAdaptors &&
454 (connector = qDBusFindAdaptorConnector(node.obj))) {
456 if (interface_name.isEmpty()) {
458 for (
const QDBusAdaptorConnector::AdaptorData &adaptorData :
459 std::as_const(connector->adaptors)) {
460 result += readAllProperties(adaptorData.adaptor,
461 QDBusConnection::ExportAllProperties);
465 QDBusAdaptorConnector::AdaptorMap::ConstIterator it;
468 if (it != connector
->adaptors.constEnd() && interface_name == QLatin1StringView(it->interface)) {
469 interfaceFound =
true;
470 result = readAllProperties(it->adaptor, QDBusConnection::ExportAllProperties);
475 if (node.flags & QDBusConnection::ExportAllProperties &&
476 (!interfaceFound || interface_name.isEmpty())) {
478 result += readAllProperties(node.obj, node.flags);
479 interfaceFound =
true;
482 if (!interfaceFound && !interface_name.isEmpty()) {
484 return interfaceNotFoundError(msg, interface_name);
487 return msg.createReply(QVariant::fromValue(result));