9#include <QtBluetooth/private/qbluetoothdevicewatcher_winrt_p.h>
10#include <QtBluetooth/private/qbluetoothutils_winrt_p.h>
11#include <QtBluetooth/private/qtbluetoothglobal_p.h>
13#include <QtCore/QLoggingCategory>
14#include <QtCore/QMutex>
15#include <QtCore/qendian.h>
17#include <winrt/Windows.Devices.Bluetooth.h>
18#include <winrt/Windows.Devices.Bluetooth.Advertisement.h>
19#include <winrt/Windows.Devices.Bluetooth.Rfcomm.h>
20#include <winrt/Windows.Devices.Bluetooth.GenericAttributeProfile.h>
21#include <winrt/Windows.Devices.Enumeration.h>
22#include <winrt/Windows.Foundation.h>
23#include <winrt/Windows.Foundation.Collections.h>
24#include <winrt/Windows.Storage.Streams.h>
26using namespace winrt::Windows::Devices::Bluetooth;
27using namespace winrt::Windows::Devices::Bluetooth::Advertisement;
28using namespace winrt::Windows::Devices::Bluetooth::GenericAttributeProfile;
29using namespace winrt::Windows::Devices::Bluetooth::Rfcomm;
30using namespace winrt::Windows::Devices::Enumeration;
31using namespace winrt::Windows::Foundation;
32using namespace winrt::Windows::Storage::Streams;
45 for (
int i = 0;
i < 16;
i++)
60 const auto data = ad.ManufacturerData();
62 const uint16_t
id =
item.CompanyId();
65 qCWarning(QT_BT_WINDOWS) <<
"Company ID already present in manufacturer data.";
66 ret.insert(
id, bufferData);
73 static constexpr int serviceDataTypes[3] = { 0x16, 0x20, 0x21 };
77 for (
const auto &serviceDataType : serviceDataTypes) {
78 const auto dataSections = ad.GetSectionsByType(serviceDataType);
79 for (
const auto §ion : dataSections) {
80 const unsigned char dataType = section.DataType();
82 if (dataType == 0x16) {
86 }
else if (dataType == 0x20) {
90 }
else if (dataType == 0x21) {
93 qFromLittleEndian<QUuid::Id128Bytes>(bufferData.
constData()))),
109 { guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3],
110 guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7] }
116 public std::enable_shared_from_this<AdvertisementWatcherWrapper>
127 m_watcher.ScanningMode(BluetoothLEScanningMode::Active);
136 unsubscribeFromEvents();
145 const ManufacturerData &manufacturerData,
146 const ServiceData &serviceData,
149 void subscribeToEvents()
153 auto thisPtr = shared_from_this();
154 m_receivedToken = m_watcher.Received(
155 [thisPtr](BluetoothLEAdvertisementWatcher,
156 BluetoothLEAdvertisementReceivedEventArgs
args) {
158 const short rssi =
args.RawSignalStrengthInDBm();
159 const BluetoothLEAdvertisement ad =
args.Advertisement();
165 const auto guids = ad.ServiceUuids();
166 for (
const auto &guid : guids) {
171 emit thisPtr->advertisementDataReceived(
address,
rssi, manufacturerData,
172 serviceData, serviceUuids);
175 void unsubscribeFromEvents()
177 m_watcher.Received(m_receivedToken);
181 const auto status = m_watcher.Status();
182 return status == BluetoothLEAdvertisementWatcherStatus::Started
183 || status == BluetoothLEAdvertisementWatcherStatus::Aborted;
186 BluetoothLEAdvertisementWatcher m_watcher;
187 winrt::event_token m_receivedToken;
194 L
"System.Devices.Aep.ProtocolId:=\"{e0cbf06c-cd8b-4647-bb8a-263b43f0f974}\"";
200 public std::enable_shared_from_this<QWinRTBluetoothDeviceDiscoveryWorker>
213 std::shared_ptr<QBluetoothDeviceWatcherWinRT> createDeviceWatcher(winrt::hstring
selector,
217 void finishDiscovery();
218 bool isFinished()
const;
221 void getClassicDeviceFromId(
const winrt::hstring &
id);
223 void handleRfcommServices(
const RfcommDeviceServicesResult &servicesResult,
227 void getLowEnergyDeviceFromId(
const winrt::hstring &
id);
228 void handleLowEnergyDevice(
const BluetoothLEDevice &
device);
229 void handleGattServices(
const GattDeviceServicesResult &servicesResult,
233 std::shared_ptr<AdvertisementWatcherWrapper> createAdvertisementWatcher();
236 Q_INVOKABLE void decrementPendingDevicesCountAndCheckFinished(
237 std::shared_ptr<QWinRTBluetoothDeviceDiscoveryWorker> worker);
242 qint16 rssi, ManufacturerData manufacturerData, ServiceData serviceData);
247 void onBluetoothDeviceFound(winrt::hstring deviceId,
int watcherId);
248 void onDeviceEnumerationCompleted(
int watcherId);
251 const ManufacturerData &manufacturerData,
252 const ServiceData &serviceData,
255 void stopAdvertisementWatcher();
258 struct LEAdvertisingInfo {
260 ManufacturerData manufacturerData;
261 ServiceData serviceData;
265 quint8 requestedModes = 0;
268 int m_pendingDevices = 0;
270 static constexpr int ClassicWatcherId = 1;
271 static constexpr int LowEnergyWatcherId = 2;
273 std::shared_ptr<QBluetoothDeviceWatcherWinRT> m_classicWatcher;
274 std::shared_ptr<QBluetoothDeviceWatcherWinRT> m_lowEnergyWatcher;
275 std::shared_ptr<AdvertisementWatcherWrapper> m_advertisementWatcher;
276 bool m_classicScanStarted =
false;
277 bool m_lowEnergyScanStarted =
false;
278 QTimer *m_leScanTimer =
nullptr;
282 std::shared_ptr<QWinRTBluetoothDeviceDiscoveryWorker> worker)
286 Q_ARG(std::shared_ptr<QWinRTBluetoothDeviceDiscoveryWorker>,
291 QBluetoothDeviceDiscoveryAgent::DiscoveryMethods
methods,
int interval)
294 qRegisterMetaType<QBluetoothDeviceInfo>();
295 qRegisterMetaType<QBluetoothDeviceInfo::Fields>();
296 qRegisterMetaType<ManufacturerData>();
297 qRegisterMetaType<std::shared_ptr<QWinRTBluetoothDeviceDiscoveryWorker>>();
302 const auto leSelector = BluetoothLEDevice::GetDeviceSelectorFromPairingState(
true);
303 m_lowEnergyWatcher = createDeviceWatcher(leSelector, LowEnergyWatcherId);
304 m_advertisementWatcher = createAdvertisementWatcher();
311 m_leScanTimer =
new QTimer(
this);
315 &QWinRTBluetoothDeviceDiscoveryWorker::stopAdvertisementWatcher);
327 if (m_classicWatcher && m_classicWatcher->init()) {
328 m_classicWatcher->start();
329 m_classicScanStarted =
true;
332 "Could not start classic device watcher");
336 if (m_lowEnergyWatcher && m_lowEnergyWatcher->init()) {
337 m_lowEnergyWatcher->start();
338 m_lowEnergyScanStarted =
true;
341 "Could not start low energy device watcher");
343 if (m_advertisementWatcher) {
344 m_advertisementWatcher->init();
345 m_advertisementWatcher->start();
347 m_leScanTimer->
start();
350 "Could not start low energy advertisement watcher");
354 qCDebug(QT_BT_WINDOWS) <<
"Worker started";
359 if (m_leScanTimer && m_leScanTimer->
isActive())
360 m_leScanTimer->
stop();
361 m_classicWatcher->stop();
362 m_lowEnergyWatcher->stop();
363 m_advertisementWatcher->stop();
366void QWinRTBluetoothDeviceDiscoveryWorker::finishDiscovery()
372bool QWinRTBluetoothDeviceDiscoveryWorker::isFinished()
const
376 return (m_pendingDevices == 0) && !m_lowEnergyScanStarted && !m_classicScanStarted
377 && (m_leScanTimer && !m_leScanTimer->
isActive());
380void QWinRTBluetoothDeviceDiscoveryWorker::onBluetoothDeviceFound(winrt::hstring deviceId,
int watcherId)
382 if (watcherId == ClassicWatcherId)
383 getClassicDeviceFromId(deviceId);
384 else if (watcherId == LowEnergyWatcherId)
385 getLowEnergyDeviceFromId(deviceId);
388void QWinRTBluetoothDeviceDiscoveryWorker::onDeviceEnumerationCompleted(
int watcherId)
390 qCDebug(QT_BT_WINDOWS) << (watcherId == ClassicWatcherId ?
"BT" :
"BTLE")
391 <<
"enumeration completed";
392 if (watcherId == ClassicWatcherId) {
393 m_classicWatcher->stop();
394 m_classicScanStarted =
false;
395 }
else if (watcherId == LowEnergyWatcherId) {
396 m_lowEnergyWatcher->stop();
397 m_lowEnergyScanStarted =
false;
404void QWinRTBluetoothDeviceDiscoveryWorker::onAdvertisementDataReceived(
409 bool needDiscoverServices =
false;
414 const LEAdvertisingInfo adInfo = m_foundLEDevicesMap.
value(
address);
416 if (adInfo.rssi !=
rssi) {
420 if (adInfo.manufacturerData != manufacturerData) {
421 m_foundLEDevicesMap[
address].manufacturerData.
insert(manufacturerData);
422 if (adInfo.manufacturerData != m_foundLEDevicesMap[
address].manufacturerData)
425 if (adInfo.serviceData != serviceData) {
426 m_foundLEDevicesMap[
address].serviceData.
insert(serviceData);
427 if (adInfo.serviceData != m_foundLEDevicesMap[
address].serviceData)
431 if (!foundServices.
contains(uuid)) {
432 foundServices.
append(uuid);
433 needDiscoverServices =
true;
436 if (!needDiscoverServices) {
440 Q_ARG(QBluetoothDeviceInfo::Fields, changedFields),
442 Q_ARG(ManufacturerData, manufacturerData),
443 Q_ARG(ServiceData, serviceData));
446 m_foundLEDevicesMap[
address].services = foundServices;
448 needDiscoverServices =
true;
449 LEAdvertisingInfo
info;
450 info.services = std::move(uuids);
451 info.manufacturerData = std::move(manufacturerData);
452 info.serviceData = std::move(serviceData);
457 if (needDiscoverServices) {
459 auto thisPtr = shared_from_this();
460 auto asyncOp = BluetoothLEDevice::FromBluetoothAddressAsync(
address);
461 asyncOp.Completed([thisPtr,
address](
auto &&op, AsyncStatus status) {
463 if (status == AsyncStatus::Completed) {
464 BluetoothLEDevice
device = op.GetResults();
466 thisPtr->handleLowEnergyDevice(
device);
471 qCDebug(QT_BT_WINDOWS) <<
"Failed to get LE device from address"
479void QWinRTBluetoothDeviceDiscoveryWorker::stopAdvertisementWatcher()
481 m_advertisementWatcher->stop();
486std::shared_ptr<QBluetoothDeviceWatcherWinRT>
487QWinRTBluetoothDeviceDiscoveryWorker::createDeviceWatcher(winrt::hstring
selector,
int watcherId)
489 auto watcher = std::make_shared<QBluetoothDeviceWatcherWinRT>(
490 watcherId,
selector, DeviceInformationKind::AssociationEndpoint);
493 this, &QWinRTBluetoothDeviceDiscoveryWorker::onBluetoothDeviceFound,
496 this, &QWinRTBluetoothDeviceDiscoveryWorker::onDeviceEnumerationCompleted,
502void QWinRTBluetoothDeviceDiscoveryWorker::generateError(
511 qCDebug(QT_BT_WINDOWS) <<
"Discovered BTLE device: " <<
info.address() <<
info.name()
512 <<
"Num UUIDs" <<
info.serviceUuids().
size() <<
"RSSI:" <<
info.rssi()
513 <<
"Num manufacturer data" <<
info.manufacturerData().
size()
514 <<
"Num service data" <<
info.serviceData().
size();
521void QWinRTBluetoothDeviceDiscoveryWorker::getClassicDeviceFromId(
const winrt::hstring &
id)
524 auto thisPtr = shared_from_this();
525 auto asyncOp = BluetoothDevice::FromIdAsync(
id);
526 asyncOp.Completed([thisPtr](
auto &&op, AsyncStatus status) {
528 if (status == AsyncStatus::Completed) {
531 thisPtr->handleClassicDevice(
device);
536 qCDebug(QT_BT_WINDOWS) <<
"Failed to get Classic device from id";
543void QWinRTBluetoothDeviceDiscoveryWorker::handleClassicDevice(
const BluetoothDevice &
device)
548 const uint32_t deviceClass =
device.ClassOfDevice().RawValue();
549 auto thisPtr = shared_from_this();
550 auto asyncOp =
device.GetRfcommServicesAsync();
551 asyncOp.Completed([thisPtr,
address, btName, deviceClass](
auto &&op, AsyncStatus status) {
553 if (status == AsyncStatus::Completed) {
554 auto servicesResult = op.GetResults();
555 if (servicesResult) {
556 thisPtr->handleRfcommServices(servicesResult,
address, btName, deviceClass);
561 qCDebug(QT_BT_WINDOWS) <<
"Failed to get RFCOMM services for device" << btName;
568void QWinRTBluetoothDeviceDiscoveryWorker::handleRfcommServices(
569 const RfcommDeviceServicesResult &servicesResult, uint64_t
address,
573 auto shared = shared_from_this();
579 const auto error = servicesResult.Error();
580 if (
error != BluetoothError::Success) {
581 qCWarning(QT_BT_WINDOWS) <<
"Obtain device services completed with BluetoothError"
582 <<
static_cast<int>(
error);
586 const auto services = servicesResult.Services();
588 for (
const auto &service :
services) {
589 const auto serviceId =
service.ServiceId();
596 qCDebug(QT_BT_WINDOWS) <<
"Discovered BT device: " << btAddress <<
name
597 <<
"Num UUIDs" << uuids.
size();
601 info.setServiceUuids(uuids);
602 info.setCached(
true);
608void QWinRTBluetoothDeviceDiscoveryWorker::decrementPendingDevicesCountAndCheckFinished(
609 std::shared_ptr<QWinRTBluetoothDeviceDiscoveryWorker> worker)
620void QWinRTBluetoothDeviceDiscoveryWorker::getLowEnergyDeviceFromId(
const winrt::hstring &
id)
623 auto asyncOp = BluetoothLEDevice::FromIdAsync(
id);
624 auto thisPtr = shared_from_this();
625 asyncOp.Completed([thisPtr](
auto &&op, AsyncStatus status) {
627 if (status == AsyncStatus::Completed) {
628 BluetoothLEDevice
device = op.GetResults();
630 thisPtr->handleLowEnergyDevice(
device);
635 qCDebug(QT_BT_WINDOWS) <<
"Failed to get LE device from id";
642void QWinRTBluetoothDeviceDiscoveryWorker::handleLowEnergyDevice(
const BluetoothLEDevice &
device)
647 const bool isPaired =
device.DeviceInformation().Pairing().IsPaired();
649 m_leDevicesMutex.
lock();
650 const LEAdvertisingInfo adInfo = m_foundLEDevicesMap.
value(
address);
651 m_leDevicesMutex.
unlock();
652 const ManufacturerData manufacturerData = adInfo.manufacturerData;
653 const ServiceData serviceData = adInfo.serviceData;
663 info.setCached(
true);
667 info.setServiceUuids(adInfo.services);
669 invokeDeviceFoundWithDebug(
info);
671 auto asyncOp =
device.GetGattServicesAsync();
672 auto thisPtr = shared_from_this();
673 asyncOp.Completed([thisPtr,
info](
auto &&op, AsyncStatus status)
mutable {
674 if (status == AsyncStatus::Completed) {
675 auto servicesResult = op.GetResults();
676 if (servicesResult) {
677 thisPtr->handleGattServices(servicesResult,
info);
682 qCDebug(QT_BT_WINDOWS) <<
"Failed to get GATT services for device" <<
info.name();
689void QWinRTBluetoothDeviceDiscoveryWorker::handleGattServices(
693 auto shared = shared_from_this();
699 const auto status = servicesResult.Status();
700 if (status == GattCommunicationStatus::Success) {
701 const auto services = servicesResult.Services();
703 for (
const auto &service :
services) {
707 info.setServiceUuids(uuids);
709 qCWarning(QT_BT_WINDOWS) <<
"Obtaining LE services finished with status"
710 <<
static_cast<int>(status);
712 invokeDeviceFoundWithDebug(
info);
715std::shared_ptr<AdvertisementWatcherWrapper>
716QWinRTBluetoothDeviceDiscoveryWorker::createAdvertisementWatcher()
718 auto watcher = std::make_shared<AdvertisementWatcherWrapper>();
721 this, &QWinRTBluetoothDeviceDiscoveryWorker::onAdvertisementDataReceived,
729 : q_ptr(
parent), adapterAddress(deviceAdapter)
736 disconnectAndClearWorker();
742 return worker !=
nullptr;
753 if (!adapter.isValid()) {
754 qCWarning(QT_BT_WINDOWS) <<
"Cannot find Bluetooth adapter for device search";
756 errorString = QBluetoothDeviceDiscoveryAgent::tr(
"Cannot find valid Bluetooth adapter.");
760 qCWarning(QT_BT_WINDOWS) <<
"Bluetooth adapter powered off";
762 errorString = QBluetoothDeviceDiscoveryAgent::tr(
"Bluetooth adapter powered off.");
770 worker = std::make_shared<QWinRTBluetoothDeviceDiscoveryWorker>(
methods,
771 lowEnergySearchTimeout);
774 discoveredDevices.
clear();
776 this, &QBluetoothDeviceDiscoveryAgentPrivate::registerDevice);
778 this, &QBluetoothDeviceDiscoveryAgentPrivate::updateDeviceData);
780 this, &QBluetoothDeviceDiscoveryAgentPrivate::onErrorOccured);
782 this, &QBluetoothDeviceDiscoveryAgentPrivate::onScanFinished);
791 disconnectAndClearWorker();
802 if (
iter->address() ==
info.address()) {
803 qCDebug(QT_BT_WINDOWS) <<
"Updating device" <<
iter->name() <<
iter->address();
808 if (
iter->serviceUuids().size() != uuidSet.size())
809 iter->setServiceUuids(uuidSet.values().toVector());
810 if (
iter->coreConfigurations() !=
info.coreConfigurations())
816 discoveredDevices <<
info;
821 QBluetoothDeviceInfo::Fields fields,
823 ManufacturerData manufacturerData,
824 ServiceData serviceData)
833 qCDebug(QT_BT_WINDOWS) <<
"Updating data for device" <<
iter->name() <<
iter->address();
855void QBluetoothDeviceDiscoveryAgentPrivate::onScanFinished()
858 disconnectAndClearWorker();
862void QBluetoothDeviceDiscoveryAgentPrivate::disconnectAndClearWorker()
868 this, &QBluetoothDeviceDiscoveryAgentPrivate::onScanFinished);
870 this, &QBluetoothDeviceDiscoveryAgentPrivate::registerDevice);
872 this, &QBluetoothDeviceDiscoveryAgentPrivate::updateDeviceData);
874 this, &QBluetoothDeviceDiscoveryAgentPrivate::onErrorOccured);
881#include <qbluetoothdevicediscoveryagent_winrt.moc>
static JNINativeMethod methods[]
IOBluetoothDevice * device
std::vector< ObjCStrongReference< CBMutableService > > services
~AdvertisementWatcherWrapper()
void advertisementDataReceived(quint64 address, qint16 rssi, const ManufacturerData &manufacturerData, const ServiceData &serviceData, const QList< QBluetoothUuid > &uuids)
AdvertisementWatcherWrapper()
~QBluetoothDeviceDiscoveryAgentPrivate()
void start(QBluetoothDeviceDiscoveryAgent::DiscoveryMethods methods)
QBluetoothDeviceDiscoveryAgentPrivate(const QBluetoothAddress &deviceAdapter, QBluetoothDeviceDiscoveryAgent *parent)
static DiscoveryMethods supportedDiscoveryMethods()
This function returns the discovery methods supported by the current platform.
void errorOccurred(QBluetoothDeviceDiscoveryAgent::Error error)
This signal is emitted when an error occurs during Bluetooth device discovery.
DiscoveryMethod
This enum descibes the type of discovery method employed by the QBluetoothDeviceDiscoveryAgent.
Error
Indicates all possible error conditions found during Bluetooth device discovery.
@ InvalidBluetoothAdapterError
@ BaseRateAndLowEnergyCoreConfiguration
@ LowEnergyCoreConfiguration
@ BaseRateCoreConfiguration
void enumerationCompleted(int id)
void deviceAdded(winrt::hstring deviceId, int id)
char * data()
\macro QT_NO_CAST_FROM_BYTEARRAY
qsizetype size() const noexcept
Returns the number of bytes in this byte array.
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
qint64 size() const
Returns the file size in bytes.
qsizetype size() const noexcept
void append(parameter_type t)
iterator insert(const Key &key, const T &value)
T value(const Key &key, const T &defaultValue=T()) const
bool contains(const Key &key) const
void unlock() noexcept
Unlocks the mutex.
void lock() noexcept
Locks the mutex.
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
\macro QT_RESTRICTED_CAST_FROM_ASCII
void clear()
Clears the contents of the string and makes it null.
static QString fromStdWString(const std::wstring &s)
Returns a copy of the str string.
void setSingleShot(bool singleShot)
void start(int msec)
Starts or restarts the timer with a timeout interval of msec milliseconds.
void setInterval(int msec)
bool isActive() const
Returns true if the timer is running (pending); otherwise returns false.
void stop()
Stops the timer.
void timeout(QPrivateSignal)
This signal is emitted when the timer times out.
void deviceDataChanged(const QBluetoothAddress &address, QBluetoothDeviceInfo::Fields, qint16 rssi, ManufacturerData manufacturerData, ServiceData serviceData)
void deviceFound(const QBluetoothDeviceInfo &info)
void errorOccured(QBluetoothDeviceDiscoveryAgent::Error error)
QWinRTBluetoothDeviceDiscoveryWorker(QBluetoothDeviceDiscoveryAgent::DiscoveryMethods methods, int interval)
~QWinRTBluetoothDeviceDiscoveryWorker()
Combined button and popup list for selecting options.
Q_CORE_EXPORT QtJniTypes::Service service()
static ManufacturerData extractManufacturerData(const BluetoothLEAdvertisement &ad)
static void invokeDecrementPendingDevicesCountAndCheckFinished(std::shared_ptr< QWinRTBluetoothDeviceDiscoveryWorker > worker)
static const winrt::hstring ClassicDeviceSelector
static GUID fromWinRtGuid(const winrt::guid &guid)
static QByteArray byteArrayFromBuffer(const IBuffer &buffer)
static ServiceData extractServiceData(const BluetoothLEAdvertisement &ad)
QT_BEGIN_NAMESPACE QUuid::Id128Bytes qbswap(const QUuid::Id128Bytes src)
void mainThreadCoInit(void *caller)
void mainThreadCoUninit(void *caller)
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter * iter
DBusConnection const char DBusError * error
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
#define qCWarning(category,...)
#define qCDebug(category,...)
#define Q_DECLARE_LOGGING_CATEGORY(name)
#define Q_ARG(Type, data)
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLuint GLuint64EXT address
GLdouble GLdouble GLdouble GLdouble q
QScopeGuard< typename std::decay< F >::type > qScopeGuard(F &&f)
[qScopeGuard]
unsigned long long quint64
QFutureWatcher< int > watcher
QFileInfo info(fileName)
[8]
QFileSelector selector
[1]
connect(quitButton, &QPushButton::clicked, &app, &QCoreApplication::quit, Qt::QueuedConnection)
myObject disconnect()
[26]
bool contains(const AT &t) const noexcept
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent